How to use sendExpand method in fMBT

Best Python code snippet using fMBT_python

fmbtwindows.py

Source:fmbtwindows.py Github

copy

Full Screen

...320 """321 Expands a widget which supports this kind of operation, like a TreeView.322 """323 self._checkUIautomation()324 self._view._device._conn.sendExpand(self.id())325 def containerItems(self, propertyName, separator="\n", filterSubChildClassName="", maxSubChildren="0", scroll=False):326 """327 Returns a list of the given property from all widget's direct328 children.329 Like the items() method, but all children, even the currently330 not displayed ones, will be reported.331 If a child isn't displayed when it's evaluated, it will332 have no sub-children, so no information about them will be333 reported. To fully render/display a child, the new scroll334 parameter should be used, so the item display area will be335 scrolled until the child is finally rendered. After that, all336 information about its sub-children are available and will be337 retrieved.338 Parameters:339 propertyName, separator, filterSubChildClassName, maxSubChildren:340 refer to ViewItem.items() documentation.341 scroll (bool, optional):342 Allows children scrolling, to make them visible.343 By default (false), no children scrolling is made.344 Note: If a widget has many children, scrolling all of them will be slow.345 """346 self._checkUIautomation()347 data = self._view._device._conn.recvViewItemContainerItems(348 self.id(), propertyName, separator, filterSubChildClassName, maxSubChildren, scroll)349 return data[0]350 def selectedItems(self, propertyName, separator="\n", filterSubChildClassName="", maxSubChildren="0", scroll=False):351 """352 Returns a list of the given property from all widget's direct353 children which are selected.354 Like containerItems(), but only selected children will be355 reported.356 """357 self._checkUIautomation()358 data = self._view._device._conn.recvViewItemSelectedItems(359 self.id(), propertyName, separator, filterSubChildClassName, maxSubChildren, scroll)360 return data[0]361 def longText(self, maxLength=65536):362 """363 Returns the text from widgets like a RichTextEdit or a Document,364 that normally don't allow to report the text using the usual text() method.365 Parameters:366 maxLength (integer, optional):367 The maximum number of characters to be reported, to368 limit the transferred data. The default is 64K characters.369 """370 self._checkUIautomation()371 data = self._view._device._conn.recvViewItemText(self.id(), maxLength)372 return data[0].popitem()[1] if data else None373 def setValue(self, value):374 """375 Sets the value of a widget. For example the text for a TextBlock,376 or the text of a ComboBox.377 It doesn't work for more complex widgets like a RichTextEdit or a Document.378 Parameters:379 value (string):380 The value to be set.381 """382 self._checkUIautomation()383 self._view._device._conn.recvViewItemSetValue(self.id(), value)384 self._properties['Value'] = str(value)385class View(object):386 def __init__(self, dumpFilename, itemTree, itemOnScreen=None, device=None, freeDumps=False):387 self._dumpFilename = dumpFilename388 self._itemTree = itemTree389 self._rootItem = None390 self._rootItems = []391 self._viewItems = {}392 self._device = device393 self._freeDumps = freeDumps394 if itemOnScreen == None:395 self._itemOnScreen = lambda item: True396 else:397 self._itemOnScreen = itemOnScreen398 if isinstance(itemTree, dict):399 # data from enumchildwindows:400 self._viewSource = "enumchildwindows"401 for itemId, winfoList in itemTree.iteritems():402 for winfo in winfoList:403 itemId, parentId, className, text, bbox = winfo404 self._viewItems[itemId] = ViewItem(405 self, itemId, parentId, className, text, bbox, dumpFilename)406 self._rootItem = self._viewItems[self._itemTree["root"][0][0]]407 self._rootItems.append(self._rootItem)408 elif isinstance(itemTree, list):409 # data from uiautomation410 # list of dictionaries, each of which contains properties of an item411 self._viewSource = "uiautomation"412 for elt in itemTree:413 self._insertItem(elt)414 if not self._rootItem and not freeDumps:415 raise ValueError("no root item in view data")416 def _insertItem(self, elt):417 bboxString = elt.get("BoundingRectangle", "0;0;0;0")418 bboxSeparator = ";" if ";" in bboxString else ","419 try:420 bbox = [int(coord) for coord in bboxString.split(bboxSeparator)]421 bbox[2] = bbox[0] + bbox[2] # width to right422 bbox[3] = bbox[1] + bbox[3] # height to bottom423 bbox = tuple(bbox)424 except Exception, e:425 bbox = 0, 0, 0, 0426 text = elt.get("Value") or elt.get("Name", "")427 vi = ViewItem(428 self, int(elt["hash"]), int(elt["parent"]),429 elt.get("ClassName", ""),430 text,431 bbox,432 self._dumpFilename,433 elt)434 self._viewItems[int(elt["hash"])] = vi435 if not vi.parent():436 self._rootItem = vi437 self._rootItems.append(vi)438 return vi439 def _checkUIautomation(self):440 if not self._viewSource.startswith("uiautomation"):441 raise NotImplementedError(442 "This method works only for uiautomation at the moment")443 def cachedItem(self, id_):444 """445 Retrieves an automation element from the server cache, passing its id.446 If the item was already into the view, it's updated.447 """448 self._checkUIautomation()449 data = self._device._conn.recvViewCachedItem(id_)450 if data:451 return self._insertItem(data[0])452 def _intCoords(self, *args):453 # TODO: relative coordinates like (0.5, 0.9)454 return [int(c) for c in args[0]]455 def filename(self):456 return self._dumpFilename457 def rootItem(self):458 return self._rootItem459 def _dumpTree(self, rootItem, indentation=''):460 yield "%s|-- %s" % (indentation, rootItem.dump())461 indentation += '| '462 for child in rootItem.children():463 for dump in self._dumpTree(child, indentation):464 yield dump465 def dumpTree(self, rootItem=None):466 """467 Returns item tree as a string468 """469 if rootItem:470 return "\n".join(self._dumpTree(rootItem))471 else:472 if self._rootItems:473 rootsDumps = ("\n".join(self._dumpTree(rootItem)) for rootItem in self._rootItems)474 else:475 rootsDumps = ("\n".join(self._dumpTree(rootItem)) for rootItem in self._viewItems.itervalues())476 return "\n".join(rootsDumps)477 def __str__(self):478 return "View(%r, %s items)" % (self._dumpFilename, len(self._viewItems))479 def findItems(self, comparator, count=-1, searchRootItem=None, searchItems=None, onScreen=False):480 foundItems = []481 if count == 0: return foundItems482 if searchRootItem != None:483 if comparator(searchRootItem) and (484 not onScreen or (self._itemOnScreen(searchRootItem))):485 foundItems.append(searchRootItem)486 for c in searchRootItem.children():487 foundItems.extend(self.findItems(comparator, count=count-len(foundItems), searchRootItem=c, onScreen=onScreen))488 else:489 if searchItems:490 domain = iter(searchItems)491 else:492 domain = self._viewItems.itervalues493 for i in domain():494 if comparator(i) and (not onScreen or (self._itemOnScreen(i))):495 foundItems.append(i)496 if count > 0 and len(foundItems) >= count:497 break498 return foundItems499 def findItemsByText(self, text, partial=False, count=-1, searchRootItem=None, searchItems=None, onScreen=False):500 if partial:501 c = lambda item: (text in item._text)502 else:503 c = lambda item: (text == item._text)504 return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)505 def findItemsByClass(self, className, partial=False, count=-1, searchRootItem=None, searchItems=None, onScreen=False):506 if partial:507 c = lambda item: (className in item._className)508 else:509 c = lambda item: (className == item._className)510 return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)511 def findItemsById(self, itemId, count=-1, searchRootItem=None, searchItems=None, onScreen=False):512 c = lambda item: (itemId == item._itemId or itemId == item.properties().get("AutomationId", None))513 return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)514 def findItemsByProperties(self, properties, count=-1, searchRootItem=None, searchItems=None, onScreen=False):515 """516 Returns ViewItems where every property matches given properties517 Parameters:518 properties (dictionary):519 names and required values of properties520 Example:521 view.findItemsByProperties({"Value": "HELLO", "Name": "File name:"})522 See also:523 viewitem.dumpProperties()524 Notes:525 - requires uiautomation (refreshView(viewSource="uiautomation"))526 - all names and values are strings527 """528 c = lambda item: 0 == len([key for key in properties529 if properties[key] != item.properties().get(key, None)])530 return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)531 def findItemsByPos(self, pos, count=-1, searchRootItem=None, searchItems=None, onScreen=False):532 """533 Returns list of ViewItems whose bounding box contains the position.534 Parameters:535 pos (pair of floats (0.0..0.1) or integers (x, y)):536 coordinates that fall in the bounding box of found items.537 other parameters: refer to findItems documentation.538 Items are listed in ascending order based on area. They may539 or may not be from the same branch in the widget hierarchy.540 """541 x, y = self._intCoords(pos)542 c = lambda item: (item.bbox()[0] <= x <= item.bbox()[2] and item.bbox()[1] <= y <= item.bbox()[3])543 items = self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)544 # sort from smallest to greatest area545 area_items = [((i.bbox()[2] - i.bbox()[0]) * (i.bbox()[3] - i.bbox()[1]), i) for i in items]546 return [i for _, i in sorted(area_items)]547 def items(self):548 """549 Returns list of all items in the view550 """551 return fmbtgti.sortItems(self._viewItems.values(), "topleft")552 def save(self, fileOrDirName):553 """554 Save view dump to a file.555 """556 shutil.copy(self._dumpFilename, fileOrDirName)557class Device(fmbtgti.GUITestInterface):558 def __init__(self, connspec=None, password=None, screenshotSize=(None, None),559 connect=True, **kwargs):560 """Connect to windows device under test.561 Parameters:562 connspec (string or None, optional):563 specification for connecting to a pythonshare564 server that will run fmbtwindows-agent. The format is565 "[socket://][password@]<host>[:<port>][/namespace]".566 The default is None: run the agent on host, do not567 connect to a pythonshare server (works only on Windows).568 password (string or None, optional):569 authenticate to pythonshare server with given570 password. The default is None (no authentication).571 rotateScreenshot (integer, optional)572 rotate new screenshots by rotateScreenshot degrees.573 Example: rotateScreenshot=-90. The default is 0 (no574 rotation).575 connect (boolean, optional):576 Immediately establish connection to the device. The577 default is True.578 To prepare a windows device for connection, launch there579 python pythonshare-server --password mysecretpwd580 When not on trusted network, consider ssh port forward, for581 instance.582 """583 fmbtgti.GUITestInterface.__init__(self, **kwargs)584 self._defaultViewSource = _g_viewSources[1]585 self._refreshViewDefaults = kwargs586 self._lastView = None587 self._lastViewStats = {}588 self._refreshViewRetryLimit = 1589 self._connspec = connspec590 self._password = password591 if connect:592 self.setConnection(WindowsConnection(593 self._connspec, self._password, self))594 else:595 self.setConnection(None)596 def closeWindow(self, window):597 """598 Send WM_CLOSE to window599 Parameters:600 window (window title (string) or handle (integer)):601 window to which the command will be sent.602 Returns True on success, otherwise False.603 """604 return self.existingConnection().sendCloseWindow(window)605 def setCacheMode(self, mode="lastwindow"):606 """607 Sets the server policy for caching AutomationElements.608 Parameters:609 mode (string, optional. Default is "lastwindow"):610 Defines the cache policy, and can be one of:611 "none", "lastdump", "lastwindow", "all".612 "none" disables caching.613 "lastdump" caches only the last dump.614 "lastwindow" caches all elements of a window.615 If a new window is dumped, the cache is616 cleared.617 "all" caches all element of all windows.618 """619 if mode not in ("none", "lastdump", "lastwindow", "all"):620 raise FMBTWindowsError("Unknown cache mode: %s" % mode)621 return self.existingConnection().sendSetCacheMode(mode)622 def clearCache(self):623 """624 Clears the server AutomationElements cache.625 """626 return self.existingConnection().sendClearCache()627 def errorReporting(self):628 """629 Returns Windows error reporting (WER) settings in a dictionary630 See also: setErrorReporting()631 MSDN WER Settings.632 """633 supported_settings = ["DisableArchive",634 "Disabled",635 "DisableQueue",636 "DontShowUI",637 "DontSendAdditionalData",638 "LoggingDisabled",639 "MaxArchiveCount",640 "MaxQueueCount"]641 settings = {}642 for setting in supported_settings:643 settings[setting] = self.getRegistry(644 r"HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting",645 setting)[0]646 return settings647 def existingView(self):648 if self._lastView:649 return self._lastView650 else:651 raise FMBTWindowsError("view is not available. Missing refreshView()?")652 def fileProperties(self, filepath):653 """654 Returns file properties as a dictionary.655 Parameters:656 filepath (string):657 full path to the file.658 """659 escapedFilename = filepath.replace('/', '\\').replace('\\', r'\\\\')660 return self.existingConnection().evalPython(661 '''wmicGet("datafile",'''662 '''componentArgs=("where", "name='%s'"))''' %663 escapedFilename)664 def getFile(self, remoteFilename, localFilename=None, compress=False):665 """666 Fetch file from the device.667 Parameters:668 remoteFilename (string):669 file to be fetched on device670 localFilename (optional, string or None):671 file to be saved to local filesystem. If None,672 return contents of the file without saving them.673 compress (optional, boolean or integer):674 if True, file contents will be compressed for the transfer.675 Integer (0-9) defines compression level. The default is676 False: transfer without compression.677 """678 return self._conn.recvFile(remoteFilename, localFilename, compress)679 def getMatchingPaths(self, pathnamePattern):680 """681 Returns list of paths matching pathnamePattern on the device.682 Parameters:683 pathnamePattern (string):684 Pattern for matching files and directories on the device.685 Example:686 getMatchingPaths("c:/windows/*.ini")687 Implementation runs glob.glob(pathnamePattern) on remote device.688 """689 return self._conn.recvMatchingPaths(pathnamePattern)690 def getClipboard(self):691 """692 Returns clipboard contents in text format.693 See also: setClipboard()694 """695 return self.existingConnection().evalPython("getClipboardText()")696 def itemOnScreen(self, guiItem, relation="touch", topWindowBbox=None):697 """698 Returns True if bbox of guiItem is non-empty and on the screen699 Parameters:700 relation (string, optional):701 One of the following:702 - "overlap": item intersects the screen and the window.703 - "touch": mid point (the default touch point) of the item704 is within the screen and the window.705 - "within": the screen and the window includes the item.706 The default is "touch".707 """708 if guiItem.properties().get("IsOffscreen", False) == "True":709 return False710 if relation == "touch":711 x1, y1, x2, y2 = guiItem.bbox()712 if x1 == x2 or y1 == y2:713 return False # a dimension is missing => empty item714 itemBox = (guiItem.coords()[0], guiItem.coords()[1],715 guiItem.coords()[0] + 1, guiItem.coords()[1] + 1)716 partial = True717 elif relation == "overlap":718 itemBox = guiItem.bbox()719 partial = True720 elif relation == "within":721 itemBox = guiItem.bbox()722 partial = False723 else:724 raise ValueError('invalid itemOnScreen relation: "%s"' % (relation,))725 maxX, maxY = self.screenSize()726 if topWindowBbox == None:727 try:728 topWindowBbox = self.topWindowProperties()['bbox']729 except TypeError:730 topWindowBbox = (0, 0, maxX, maxY)731 return (fmbtgti._boxOnRegion(itemBox, (0, 0, maxX, maxY), partial=partial) and732 fmbtgti._boxOnRegion(itemBox, topWindowBbox, partial=partial))733 def kill(self, pid):734 """735 Terminate process736 Parameters:737 pid (integer):738 ID of the process to be terminated.739 """740 try:741 return self.existingConnection().evalPython(742 "kill(%s)" % (repr(pid),))743 except:744 return False745 def keyNames(self):746 """747 Returns list of key names recognized by pressKey748 """749 return sorted(_g_keyNames)750 def osProperties(self):751 """752 Returns OS properties as a dictionary753 """754 return self.existingConnection().evalPython(755 "wmicGet('os')")756 def pinch(self, (x, y), startDistance, endDistance,757 finger1Dir=90, finger2Dir=270, movePoints=20,758 duration=0.75):759 """760 Pinch (open or close) on coordinates (x, y).761 Parameters:762 x, y (integer):763 the central point of the gesture. Values in range764 [0.0, 1.0] are scaled to full screen width and765 height.766 startDistance, endDistance (float):767 distance from both finger tips to the central point768 of the gesture, at the start and at the end of the769 gesture. Values in range [0.0, 1.0] are scaled up to770 the distance from the coordinates to the edge of the771 screen. Both finger tips will reach an edge if772 distance is 1.0.773 finger1Dir, finger2Dir (integer, optional):774 directions for finger tip movements, in range [0,775 360]. 0 is to the east, 90 to the north, etc. The776 defaults are 90 and 270.777 movePoints (integer, optional):778 number of points to which finger tips are moved779 after laying them to the initial positions. The780 default is 20.781 duration (float, optional):782 duration of the gesture in seconds, the default is 0.75.783 """784 screenWidth, screenHeight = self.screenSize()785 screenDiagonal = math.sqrt(screenWidth**2 + screenHeight**2)786 if x == None: x = 0.5787 if y == None: y = 0.5788 x, y = self.intCoords((x, y))789 if type(startDistance) == float and 0.0 <= startDistance <= 1.0:790 startDistanceInPixels = (791 startDistance *792 min(fmbtgti._edgeDistanceInDirection((x, y), self.screenSize(), finger1Dir),793 fmbtgti._edgeDistanceInDirection((x, y), self.screenSize(), finger2Dir)))794 else:795 startDistanceInPixels = int(startDistance)796 if type(endDistance) == float and 0.0 <= endDistance <= 1.0:797 endDistanceInPixels = (798 endDistance *799 min(fmbtgti._edgeDistanceInDirection((x, y), self.screenSize(), finger1Dir),800 fmbtgti._edgeDistanceInDirection((x, y), self.screenSize(), finger2Dir)))801 else:802 endDistanceInPixels = int(endDistance)803 finger1startX = int(x + math.cos(math.radians(finger1Dir)) * startDistanceInPixels)804 finger1startY = int(y - math.sin(math.radians(finger1Dir)) * startDistanceInPixels)805 finger1endX = int(x + math.cos(math.radians(finger1Dir)) * endDistanceInPixels)806 finger1endY = int(y - math.sin(math.radians(finger1Dir)) * endDistanceInPixels)807 finger2startX = int(x + math.cos(math.radians(finger2Dir)) * startDistanceInPixels)808 finger2startY = int(y - math.sin(math.radians(finger2Dir)) * startDistanceInPixels)809 finger2endX = int(x + math.cos(math.radians(finger2Dir)) * endDistanceInPixels)810 finger2endY = int(y - math.sin(math.radians(finger2Dir)) * endDistanceInPixels)811 self.existingConnection().sendPinch(812 (finger1startX, finger1startY), (finger1endX, finger1endY),813 (finger2startX, finger2startY), (finger2endX, finger2endY),814 movePoints, duration)815 return True816 def pinchOpen(self, (x, y) = (0.5, 0.5), startDistance=0.1, endDistance=0.5, **pinchKwArgs):817 """818 Make the open pinch gesture.819 Parameters:820 x, y (integer, optional):821 the central point of the gesture, the default is in822 the middle of the screen.823 startDistance, endDistance (float, optional):824 refer to pinch documentation. The default is 0.1 and825 0.5.826 for the rest of the parameters, refer to pinch documentation.827 """828 return self.pinch((x, y), startDistance, endDistance, **pinchKwArgs)829 def pinchClose(self, (x, y) = (0.5, 0.5), startDistance=0.5, endDistance=0.1, **pinchKwArgs):830 """831 Make the close pinch gesture.832 Parameters:833 x, y (integer, optional):834 the central point of the gesture, the default is in835 the middle of the screen.836 startDistance, endDistance (float, optional):837 refer to pinch documentation. The default is 0.5 and838 0.1.839 rest of the parameters: refer to pinch documentation.840 """841 return self.pinch((x, y), startDistance, endDistance, **pinchKwArgs)842 def putFile(self, localFilename, remoteFilepath, data=None):843 """844 Send local file to the device.845 Parameters:846 localFilename (string):847 file to be sent.848 remoteFilepath (string):849 destination on the device. If destination is an850 existing directory, the file will be saved to the851 directory with its original local name. Otherwise the file852 will be saved with remoteFilepath as new name.853 data (string, optional):854 data to be stored to remoteFilepath. The default is855 the data in the local file.856 Example: Copy local /tmp/file.txt to c:/temp857 putFile("/tmp/file.txt", "c:/temp/")858 Example: Create new remote file859 putFile(None, "c:/temp/file.txt", "remote file contents")860 """861 return self._conn.sendFile(localFilename, remoteFilepath, data)862 def rmFile(self, remoteFilepath):863 """864 Remove a file from the device.865 Parameters:866 remoteFilepath (string):867 file to be removed from the device.868 """869 return self.existingConnection().evalPython(870 "os.remove(%s)" % (repr(remoteFilepath),))871 def reconnect(self, connspec=None, password=None):872 """873 Close connections to the device and reconnect.874 Parameters:875 connspec (string, optional):876 Specification for new connection. The default is current877 connspec.878 password (string, optional):879 Password for new connection. The default is current password.880 """881 self.setConnection(None)882 import gc883 gc.collect()884 if connspec != None:885 self._connspec = connspec886 if password != None:887 self._password = password888 if self._connspec == None:889 _adapterLog("reconnect failed: missing connspec")890 return False891 try:892 self.setConnection(WindowsConnection(893 self._connspec, self._password, self))894 return True895 except Exception, e:896 _adapterLog("reconnect failed: %s" % (e,))897 return False898 def getDumpFilename(self, suffix):899 if self.screenshotDir() == None:900 self.setScreenshotDir(self._screenshotDirDefault)901 if self.screenshotSubdir() == None:902 self.setScreenshotSubdir(self._screenshotSubdirDefault)903 return self._newScreenshotFilepath()[:-3] + suffix904 def refreshView(self, window=None, forcedView=None, viewSource=None,905 items=None, properties=None, area=None,906 filterType="none", filterCondition="",907 dumpChildClass="", dumpChildName="", doNotDump=False):908 """909 (Re)reads widgets on the top window and updates the latest view.910 Parameters:911 window (integer (hWnd) or string (title), optional):912 read widgets from given window instead of the top window.913 forcedView (View or filename, optional):914 use given View object or view file instead of reading the915 items from the device.916 viewSource (string, optional):917 source of UI information. Supported sources are:918 "uiautomation" the UIAutomation framework.919 "enumchildwindows" less data920 but does not require UIAutomation.921 The default is "uiautomation".922 You can define TreeWalker used by "uiautomation" by defining923 viewSource as "uiautomation/raw", "uiautomation/control" or924 "uiautomation/content".925 See also setViewSource().926 items (list of view items, optional):927 update only contents of these items in the view.928 Works only for "uiautomation" view source.929 properties (list of property names, optional):930 read only given properties from items, the default931 is to read all available properties.932 Works only for "uiautomation" view source.933 See also setViewSource().934 area ((left, top, right, bottom), optional):935 refresh only items that intersect the area.936 The default is None: locations do not affect refreshed937 items.938 filterType (string, optional):939 specify how the widgets should be filtered.940 Supported values are:941 "none", which is the default, which means that all widgets942 will be retrieved.943 "first": only the first element which satisfy the condition944 defined by the filterCondition parameter is returned.945 "all": all elements which satisfy the condition defined by946 the filterCondition parameter are returned.947 "first" and "all" allow to specify an additional "+children"948 qualifier, which returns also all element's children.949 So, passing "first+children" as filterType, then the element950 all its children are returned, if the element (and only it)951 satisfy filterCondition.952 It's import to underline that the conditions defined by the953 items, properties, and area, parameters are still all954 applied on top of filterType and filterCondition.955 filterCondition (string, optional):956 specify the condition for filtering the widgets.957 It only works if filterType is not "none".958 Currently only a basic filter conditions are supported, that959 allows to specify a property name, the == operator, and960 a double-quoted string with the value to be compared.961 Filter conditions can be chained together using the "and"962 operator; this allows more fine-grained filtering.963 For example:964 'ClassName == "ToolBar" and Name == "Explorer"'965 matches all widgets whose "ClassName" property is equal966 to "ToolBar" and the Name is "Explorer".967 The list of currently allowed properties is the following:968 AutomationId, ClassName, HelpText, LabeledBy, Name.969 dumpChildClass (string, optional):970 if specified, only widgets of this class will be dumped /971 reported. Otherwise all widgets will be dumped (if no other972 dumping option is given. See below).973 For example, setting dumpChildClass to "TextBlock" will974 return only this kind of widgets.975 Imagine a big ListView, where a single ListViewItem is a976 complex container / panel which incorporates several widgets,977 but you don't want to dump all of them, and you're interested978 only to the ones which carry textual information.979 You can do this using the filtering options to catch the980 ListView widget and visiting all its children/descendants,981 but setting dumpChildClass will give back only the TextBlocks.982 So, this is quite different from the above filtering options,983 because filtering only defines how the UI widgets are984 traversed (and eventually cached), whereas dumping defines985 what widgets will be really reported back and collected by986 the view.987 Filtering reduces the amount of widgets that will be988 evaluated. On top of that, dumping reduces the number of989 widgets that will be returned back to the view.990 dumpChildName (string, optional):991 if specified, only widgets with this name will be dumped /992 reported. Otherwise all widgets will be dumped (if no other993 dumping option is given).994 It works exactly like dumpChildClass, but works on the Name995 property. So, the same logic applies.996 It can be combined with dumpChildClass to further reduce the997 number of returned widgets.998 For example, dumpChildName = "Foo" will give back all widgets999 which have "Foo" as Name.1000 doNotDump (boolean, optional):1001 if specified, no widgets will be dumped / reported, regarding1002 of all other dump options.1003 It's used to only cache the widgets in the server. All widgets1004 will be traversed and cached (if a cache option is defined).1005 See also setRefreshViewDefaults().1006 Returns View object.1007 """1008 if window == None:1009 window = self._refreshViewDefaults.get("window", None)1010 if forcedView == None:1011 forcedView = self._refreshViewDefaults.get("forcedView", None)1012 if viewSource == None:1013 viewSource = self.viewSource()1014 if not viewSource in _g_viewSources:1015 raise ValueError('invalid view source "%s"' % (viewSource,))1016 if items == None:1017 items = self._refreshViewDefaults.get("items", [])1018 if properties == None:1019 properties = self._refreshViewDefaults.get("properties", None)1020 if area == None:1021 area = self._refreshViewDefaults.get("area", None)1022 if forcedView != None:1023 retryCount = 01024 startTime = time.time()1025 lastStartTime = startTime1026 viewFilename = forcedView1027 if isinstance(forcedView, View):1028 self._lastView = forcedView1029 elif type(forcedView) in [str, unicode]:1030 try:1031 self._lastView = View(1032 forcedView, ast.literal_eval(file(viewFilename).read()),1033 device=self, freeDumps=dumpChildClass or dumpChildName or doNotDump)1034 except Exception:1035 self._lastView = None1036 endTime = time.time()1037 else:1038 viewFilename = self.getDumpFilename("view")1039 retryCount = 01040 startTime = time.time()1041 lastStartTime = startTime1042 while True:1043 try:1044 topWindowBbox = self.topWindowProperties()['bbox']1045 except TypeError:1046 topWindowBbox = None # top window unavailable1047 if area:1048 leftTopRightBottom = (1049 self.intCoords((area[0], area[1])) +1050 self.intCoords((area[2], area[3])))1051 else:1052 leftTopRightBottom = None1053 if viewSource == "enumchildwindows":1054 viewData = self._conn.recvViewData(window)1055 else:1056 if "/" in viewSource:1057 walker = viewSource.split("/")[1]1058 else:1059 walker = "raw"1060 if properties != None:1061 if properties == "all":1062 viewItemProperties = None1063 elif properties == "fast":1064 viewItemProperties = ["AutomationId",1065 "BoundingRectangle",1066 "ClassName",1067 "HelpText",1068 "ToggleState",1069 "Value",1070 "Minimum",1071 "Maximum",1072 "Name"]1073 elif isinstance(properties, list) or isinstance(properties, tuple):1074 viewItemProperties = list(properties)1075 else:1076 raise ValueError('invalid properties argument, expected "all", '1077 '"fast" or a list')1078 else:1079 viewItemProperties = properties1080 viewData = self._conn.recvViewUIAutomation(1081 window, items, viewItemProperties, leftTopRightBottom, walker,1082 filterType, filterCondition, dumpChildClass, dumpChildName, doNotDump)1083 file(viewFilename, "w").write(repr(viewData))1084 try:1085 self._lastView = View(1086 viewFilename, viewData,1087 itemOnScreen=lambda i: self.itemOnScreen(i, topWindowBbox=topWindowBbox),1088 device=self, freeDumps=dumpChildClass or dumpChildName or doNotDump)1089 break1090 except Exception, e:1091 self._lastView = None1092 _adapterLog(1093 "refreshView %s failed (%s), source=%s topWindow=%s" %1094 (retryCount, e, repr(viewSource), self.topWindow()))1095 retryCount += 11096 if retryCount < self._refreshViewRetryLimit:1097 time.sleep(0.2)1098 else:1099 break1100 lastStartTime = time.time()1101 endTime = time.time()1102 itemCount = -11103 if self._lastView:1104 itemCount = len(self._lastView._viewItems)1105 self._lastViewStats = {1106 "retries": retryCount,1107 "timestamp": endTime,1108 "total time": endTime - startTime,1109 "last time": endTime - lastStartTime,1110 "filename": viewFilename,1111 "source": viewSource,1112 "forced": (forcedView != None),1113 "window": window,1114 "view": str(self._lastView),1115 "item count": itemCount}1116 return self._lastView1117 def refreshViewDefaults(self):1118 """Returns default arguments for refreshView() calls.1119 See also setRefreshViewDefaults().1120 """1121 return dict(self._refreshViewDefaults)1122 def setClipboard(self, data):1123 """1124 Set text on clipboard1125 Parameters:1126 data (string):1127 data to be set on the clipboard.1128 Note: any type of data on clipboard will be emptied.1129 See also: getClipboard()1130 """1131 return self.existingConnection().evalPython(1132 "setClipboardText(%s)" % (repr(data),))1133 def setErrorReporting(self, settings):1134 """1135 Modify Windows error reporting settings (WER)1136 Parameters:1137 settings (dictionary):1138 WER settings and values to be set.1139 Example: disable showing interactive crash dialogs1140 setErrorReporting({"DontShowUI": 1})1141 See also: errorReporting(),1142 MSDN WER Settings.1143 """1144 for setting in settings:1145 self.setRegistry(1146 r"HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting",1147 setting, settings[setting])1148 return True1149 def setDisplaySize(self, size):1150 """1151 Transform coordinates of synthesized events (like a tap) from1152 screenshot resolution to display input area size. By default1153 events are synthesized directly to screenshot coordinates.1154 Parameters:1155 size (pair of integers: (width, height)):1156 width and height of display in pixels. If not given,1157 values from EnumDisplayMonitors are used.1158 Returns None.1159 """1160 width, height = size1161 screenWidth, screenHeight = self.screenSize()1162 self._conn.setScreenToDisplayCoords(1163 lambda x, y: (x * width / screenWidth,1164 y * height / screenHeight))1165 self._conn.setDisplayToScreenCoords(1166 lambda x, y: (x * screenWidth / width,1167 y * screenHeight / height))1168 def setForegroundWindow(self, window):1169 """1170 Set a window with the title as a foreground window1171 Parameters:1172 window (title (string) or hwnd (integer):1173 title or handle of the window to be raised1174 foreground.1175 Returns True if the window was brought to the foreground,1176 otherwise False.1177 Notes: calls SetForegroundWindow in user32.dll.1178 """1179 return self.existingConnection().sendSetForegroundWindow(window)1180 def setRefreshViewDefaults(self, **kwargs):1181 """Set new default arguments for refreshView() calls1182 Parameters:1183 **kwargs (keyword arguments)1184 new default values for optional refreshView() parameters.1185 Note: default arguments are overridden by arguments given1186 directly in refreshView calls.1187 Note: setViewSource() can change the default arguments.1188 Example:1189 setRefreshViewDefaults(window="My app title",1190 viewSource="uiautomation/content")1191 """1192 self._refreshViewDefaults = kwargs1193 def findRegistry(self, rootKey, key=None, valueName=None, limit=1):1194 """Search for key and/or valueName from the registry.1195 Returns a list of matching (fullKeyPath, valueName) pairs1196 found under the rootKey. The list has at most limit items, the1197 default is 1.1198 Parameters:1199 rootKey (string):1200 root key path for the search. Example:1201 "HKEY_LOCAL_MACHINE".1202 key (string, optional):1203 key name to be searched for under the rootKey.1204 The key is a regular expression that is searched for1205 from full key path. Use "\\name$" to require exact1206 match.1207 If not given, valueName should be defined.1208 valueName (string, optional):1209 value name to be searched for under the rootKey.1210 The value can be a regular expression.1211 If not given, key should be defined and1212 returned valueName will be None.1213 limit (integer, optional):1214 maximum number of matches to be returned. The1215 default is 1. limit=None returns all matching1216 pairs.1217 Example:1218 findRegistry("HKEY_LOCAL_MACHINE", key="\\Windows$")1219 """1220 if key == None and valueName == None:1221 raise ValueError("either key or valueName must be provided")1222 return self.existingConnection().evalPython(1223 'findRegistry(%s, key=%s, valueName=%s, limit=%s)' % (1224 repr(rootKey), repr(key), repr(valueName), repr(limit)))1225 def setRegistry(self, key, valueName, value, valueType=None):1226 """1227 Set Windows registry value.1228 Parameters:1229 key (string):1230 full key name.1231 valueName (string):1232 name of the value to be set.1233 value (string):1234 string that specifies the new value.1235 valueType (string, optional for str and int values):1236 REG_BINARY, REG_DWORD, REG_DWORD_LITTLE_ENDIAN,1237 REG_DWORD_BIG_ENDIAN, REG_EXPAND_SZ, REG_LINK,1238 REG_MULTI_SZ, REG_NONE, REG_RESOURCE_LIST or REG_SZ.1239 Default types for storing str and int values1240 are REG_SZ and REG_DWORD.1241 Example:1242 setRegistry(r"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet"1243 "\Control\Session Manager\Environment",1244 "PATH", r"C:\MyExecutables", "REG_EXPAND_SZ")1245 Returns True on success.1246 """1247 return self.existingConnection().evalPython(1248 "setRegistry(%s,%s,%s,%s)" % (repr(key), repr(valueName),1249 repr(value), repr(valueType)))1250 def getRegistry(self, key, valueName):1251 """1252 Return Windows registry value and type1253 Parameters:1254 key (string):1255 full key name.1256 valueName (string):1257 name of the value to be read.1258 Returns a pair (value, valueType)1259 Example:1260 getRegistry(r"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet"1261 "\Control\Session Manager\Environment", "PATH")1262 """1263 return self.existingConnection().evalPython(1264 "getRegistry(%s,%s)" % (repr(key), repr(valueName)))1265 def processList(self):1266 """1267 Return list of processes running on the device.1268 Returns list of dictionaries with keys:1269 "pid": process ID, and1270 "ProcessImageFileName": full path to the executable in win32 format.1271 """1272 return self.existingConnection().evalPython("processList()")1273 def processStatus(self, pid):1274 """1275 Return status of a process1276 Parameters:1277 pid (integer):1278 Process ID of the process1279 Returns properties in a dictionary.1280 Example:1281 print "Memory usage:", processStatus(4242)["WorkingSetSize"]1282 """1283 return self.existingConnection().evalPython(1284 "processStatus(%s)" % (repr(pid),))1285 def productList(self):1286 """1287 Return list of products installed or advertised in the system1288 Returns list of dictionaries, each containing properties of a product.1289 """1290 return self.existingConnection().evalPython("products()")1291 def pycosh(self, command):1292 """1293 Run command in pycosh shell on the device.1294 Parameters:1295 command (string):1296 pycosh command to be executed. Pycosh implements1297 stripped-down versions of zip, tar, find, md5sum, diff,1298 grep, head, tail, curl,... the usual handy shell utils.1299 For information on pycosh commands, try1300 device.pycosh("help") or run in shell:1301 echo help | python -m pycosh.1302 """1303 return self.existingConnection().pycosh(command)1304 def setScreenshotSize(self, size):1305 """1306 Force screenshots from device to use given resolution.1307 Overrides detected monitor resolution on device.1308 Parameters:1309 size (pair of integers: (width, height)):1310 width and height of screenshot.1311 """1312 self._conn.setScreenshotSize(size)1313 def setTopWindow(self, window):1314 """1315 Set a window as a foreground window and bring it to front.1316 Parameters:1317 window (title (string) or hwnd (integer):1318 title or handle of the window to be raised1319 foreground.1320 Returns True if the window was brought to the foreground,1321 otherwise False.1322 Notes: calls SetForegroundWindow in user32.dll.1323 """1324 return self.existingConnection().sendSetTopWindow(window)1325 def setViewSource(self, source, properties=None):1326 """1327 Set default view source for refreshView()1328 Parameters:1329 source (string):1330 default source, "enumchildwindow" or "uiautomation",1331 "uiautomation/raw", "uiautomation/control",1332 "uiautomation/content".1333 properties (string or list of strings, optional):1334 set list of view item properties to be read.1335 "all" reads all available properties for each item.1336 "fast" reads a set of preselected properties.1337 list of strings reads properties in the list.1338 The default is "all".1339 Returns None.1340 See also refreshView(), viewSource(), refreshViewDefaults().1341 """1342 if not source in _g_viewSources:1343 raise ValueError(1344 'invalid view source "%s", expected one of: "%s"' %1345 (source, '", "'.join(_g_viewSources)))1346 if properties != None:1347 self._refreshViewDefaults["properties"] = properties1348 self._refreshViewDefaults["viewSource"] = source1349 def shell(self, command):1350 """1351 Execute command in Windows.1352 Parameters:1353 command (string or list of strings):1354 command to be executed. Will be forwarded directly1355 to subprocess.check_output. If command is a string,1356 then it will be executed in subshell, otherwise without1357 shell.1358 Returns what is printed by the command.1359 If you wish to receive exitstatus or standard output and error1360 separated from command, refer to shellSOE().1361 """1362 return self._conn.evalPython('shell(%s)' % (repr(command),))1363 def shellSOE(self, command, asyncStatus=None, asyncOut=None,1364 asyncError=None, cwd=None, timeout=None, env=None):1365 """Execute command on Windows.1366 Parameters:1367 command (string or list of strings):1368 command to be executed. If command is a list of1369 string, it will be executed without shell1370 (subprocess.check_output with shell=False).1371 If command is a single-line string, it will be1372 executed in shell (subprocess.check_output with1373 shell=True).1374 If command is a multiline string, it will be written1375 to a BAT file and executed as a script.1376 asyncStatus (string, True or None)1377 filename (on device) to which the status of1378 asynchronously executed shellCommand will be1379 written. If True, the command will be executed1380 asynchronously but exit status will not be1381 saved. The default is None, that is, command will be1382 run synchronously, and status will be returned in1383 the tuple.1384 asyncOut (string, True or None)1385 filename (on device) to which the standard output of1386 asynchronously executed shellCommand will be1387 written. If True, the command will be executed1388 asynchronously but output will not saved. The1389 default is None.1390 asyncError (string, True or None)1391 filename (on device) to which the standard error of1392 asynchronously executed shellCommand will be1393 written. If True, the command will be executed1394 asynchronously but standard error will not be1395 saved. The default is None.1396 cwd (string, optional)1397 current working directory in which the command1398 will be executed. If not given, the cwd defaults1399 to the current working directory of the pythonshare1400 server process on the device, or the cwd of the Python1401 process if executed on host without pythonshare-server.1402 timeout (float, optional)1403 forcefully kill child processes and return after1404 given time (in seconds). If timed out, returned output1405 and error strings contain what was printed until processes1406 were killed. Returned status is a fmbtwindows.Timeout1407 instance. Asynchronous executions cannot be timed out.1408 The default is None (no timeout).1409 env (dictionary, optional)1410 defines variables and values for the environment1411 where the command will be executed.1412 - Variables that are not in the dictionary are1413 inherited from the pythonshare-server environment on1414 DUT.1415 - Variables with value None are removed from1416 inherited environment.1417 - Variables with string values override inherited1418 variables.1419 The default is None (no changes to inherited1420 environment).1421 Example: unset TEMPDIR and override default PATH1422 env={"TEMPDIR": None, "PATH": r"c:\windows\system32"}1423 Returns triplet: exit status, standard output and standard error1424 (int, str, str) from the command.1425 If executing command fails, returns (None, None, None).1426 If execution is timed out, returns (fmbtwindows.Timeout, str, str)1427 or (fmbtwindows.Timeout, None, None) if outputs could not be read.1428 """1429 if (timeout != None and1430 (asyncStatus, asyncOut, asyncError) != (None, None, None)):1431 raise NotImplementedError(1432 "timeout for asynchronous execution is not supported")1433 s, o, e = self._conn.evalPython(1434 'shellSOE(%s, asyncStatus=%s, asyncOut=%s, asyncError=%s, '1435 'cwd=%s, timeout=%s, env=%s)'1436 % (repr(command),1437 repr(asyncStatus), repr(asyncOut), repr(asyncError),1438 repr(cwd), repr(timeout), repr(env)))1439 if isinstance(s, str) and s.startswith("TIMEOUT"):1440 s = Timeout(command=command[:1024*8],1441 pid=int(s.split()[-1]))1442 return s, o, e1443 def showWindow(self, window, showCmd=SW_NORMAL):1444 """1445 Send showCmd to window.1446 Parameters:1447 window (window title (string) or handle (integer)):1448 window to which the command will be sent.1449 showCmd (integer or string):1450 command to be sent. Valid commands are 0..11:1451 SW_HIDE, SW_NORMAL, SW_MINIMIZED, SW_MAXIMIZE,1452 SW_NOACTIVATE, SW_SHOW SW_MINIMIZE, SW_MINNOACTIVE,1453 SW_SHOWNA, SW_RESTORE, SW_DEFAULT, SW_FORCEMINIMIZE.1454 Returns True if the window was previously visible,1455 otherwise False.1456 Notes: calls ShowWindow in user32.dll.1457 """1458 return self.existingConnection().sendShowWindow(window, showCmd)1459 def tapText(self, text, partial=False, **tapKwArgs):1460 """1461 Find an item with given text from the latest view, and tap it.1462 Parameters:1463 partial (boolean, optional):1464 refer to verifyText documentation. The default is1465 False.1466 tapPos (pair of floats (x, y)):1467 refer to tapItem documentation.1468 button, long, hold, count, delayBetweenTaps (optional):1469 refer to tap documentation.1470 Returns True if successful, otherwise False.1471 """1472 items = self.existingView().findItemsByText(text, partial=partial, count=1, onScreen=True)1473 if len(items) == 0: return False1474 return self.tapItem(items[0], **tapKwArgs)1475 def topWindow(self):1476 """1477 Returns a handle to the window.1478 """1479 return self.existingConnection().evalPython(1480 "ctypes.windll.user32.GetForegroundWindow()")1481 def topWindowProperties(self):1482 """1483 Return properties of the top window as a dictionary1484 """1485 return self._conn.recvTopWindowProperties()1486 def verifyText(self, text, partial=False):1487 """1488 Verify that the last view has at least one item with given1489 text.1490 Parameters:1491 text (string):1492 text to be searched for in items.1493 partial (boolean, optional):1494 if True, match items if item text contains given1495 text, otherwise match only if item text is equal to1496 the given text. The default is False (exact match).1497 """1498 assert self._lastView != None, "View required."1499 return self._lastView.findItemsByText(text, partial=partial, count=1, onScreen=True) != []1500 def viewSource(self):1501 """1502 Returns current default view source.1503 See also refreshView(), setViewSource().1504 """1505 return self._refreshViewDefaults.get(1506 "viewSource", self._defaultViewSource)1507 def windowList(self):1508 """1509 Return list of properties of windows (dictionaries)1510 Example: list window handles and titles:1511 for props in d.windowList():1512 print props["hwnd"], props["title"]1513 """1514 return self._conn.recvWindowList()1515 def windowProperties(self, window):1516 """1517 Returns properties of a window.1518 Parameters:1519 window (title (string) or hwnd (integer):1520 The window whose properties will be returned.1521 Returns properties in a dictionary.1522 """1523 return self.existingConnection().recvWindowProperties(window)1524 def windowStatus(self, window):1525 """1526 Returns status of a window.1527 Parameters:1528 window (title (string) or hwnd (integer):1529 The window whose properties will be returned.1530 Returns status in a dictionary.1531 """1532 return self.existingConnection().recvWindowStatus(window)1533 def view(self):1534 return self._lastView1535 def viewStats(self):1536 return self._lastViewStats1537class _NoPythonshareConnection(object):1538 """Fake Pythonshare connection, evaluate everything locally"""1539 def __init__(self, namespace="default"):1540 self._namespaces = {}1541 self._ns = namespace1542 def exec_in(self, ns, code):1543 if not ns in self._namespaces:1544 self._namespaces[ns] = {}1545 exec code in self._namespaces[ns]1546 def eval_in(self, ns, expr):1547 if not ns in self._namespaces:1548 self._namespaces[ns] = {}1549 return eval(expr, self._namespaces[ns])1550 def namespace(self):1551 return self._ns1552class WindowsConnection(fmbtgti.GUITestConnection):1553 def __init__(self, connspec, password, device):1554 fmbtgti.GUITestConnection.__init__(self)1555 self._device = device1556 self._screenshotSize = (None, None) # autodetect1557 self._pycosh_sent_to_dut = False1558 if connspec != None:1559 self._agent = pythonshare.connect(connspec, password=password)1560 else:1561 if os.name != "nt":1562 raise ValueError("connecting to host works only on Windows")1563 self._agent = _NoPythonshareConnection()1564 self._agent_ns = self._agent.namespace()1565 agentFilename = os.path.join(1566 os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))),1567 "fmbtwindows_agent.py")1568 self._agent.exec_in(self._agent_ns, file(agentFilename).read())1569 self.setScreenToDisplayCoords(lambda x, y: (x, y))1570 self.setDisplayToScreenCoords(lambda x, y: (x, y))1571 def pycosh(self, command):1572 if not self._pycosh_sent_to_dut:1573 # upload pycosh module to DUT1574 try:1575 self.evalPython("len(_g_pycosh_source)")1576 except pythonshare.RemoteEvalError:1577 self.execPython(file(inspect.getsourcefile(pycosh)).read())1578 self._pycosh_sent_to_dut = True1579 return self.evalPython("pycosh_eval(%s)" % (repr(command),))1580 def setScreenshotSize(self, screenshotSize):1581 self._screenshotSize = screenshotSize1582 screenW, screenH = self._screenshotSize1583 inputW, inputH = self._agent.eval_in(self._agent_ns, "_mouse_input_area")1584 self.setScreenToDisplayCoords(1585 lambda x, y: (x * inputW / screenW, y * inputH / screenH))1586 self.setDisplayToScreenCoords(1587 lambda x, y: (x * screenW / inputW, y * screenH / inputH))1588 def execPython(self, code):1589 return self._agent.exec_in(self._agent_ns, code)1590 def evalPython(self, code):1591 return self._agent.eval_in(self._agent_ns, code)1592 def recvFile(self, remoteFilename, localFilename=None, compress=False):1593 if compress:1594 if isinstance(compress, int):1595 compressLevel = compress1596 else:1597 compressLevel = 31598 data_b64_z = self._agent.eval_in(1599 self._agent_ns,1600 "base64.b64encode(zlib.compress(file(%s, 'rb').read(), %s))" % (1601 repr(remoteFilename), compressLevel))1602 data = zlib.decompress(base64.b64decode(data_b64_z))1603 else:1604 data_b64 = self._agent.eval_in(1605 self._agent_ns,1606 "base64.b64encode(file(%s, 'rb').read())" % (repr(remoteFilename),))1607 data = base64.b64decode(data_b64)1608 if localFilename:1609 file(localFilename, "wb").write(data)1610 return True1611 else:1612 return data1613 def sendFile(self, localFilename, remoteFilepath, data=None):1614 sendBlockMaxLen = 10 * 1024 * 1024 # Send at most 10 MB at a time1615 sendDataFromFile = False1616 if data == None:1617 fileSize = os.stat(localFilename).st_size1618 if fileSize < sendBlockMaxLen:1619 data = open(localFilename, "rb").read()1620 else:1621 data = ""1622 dataFile = open(localFilename, "rb")1623 sendDataFromFile = True1624 if localFilename:1625 basename = os.path.basename(localFilename)1626 else:1627 basename = localFilename1628 if sendDataFromFile:1629 dataLen = fileSize1630 else:1631 dataLen = len(data)1632 sendIndex = 01633 while sendIndex < dataLen or dataLen == 0:1634 if sendDataFromFile:1635 sendData = dataFile.read(sendBlockMaxLen)1636 else:1637 sendData = data[sendIndex:sendIndex + sendBlockMaxLen]1638 rv = self.evalPython(1639 'saveFile(%s, %s, base64.b64decode(%s), append=%s)' %1640 (repr(basename),1641 repr(remoteFilepath),1642 repr(base64.b64encode(sendData)),1643 repr(sendIndex != 0)))1644 sendIndex += sendBlockMaxLen1645 if not rv or dataLen == 0:1646 break1647 if sendDataFromFile:1648 dataFile.close()1649 return rv1650 def recvMatchingPaths(self, pathnamePattern):1651 filepaths = self._agent.eval_in(1652 self._agent_ns,1653 "glob.glob(%s)" % (repr(pathnamePattern),))1654 if "/" in pathnamePattern:1655 # Unix-style directory naming in input,1656 # stick with it and fix mixed / and \ that might1657 # come out from glob.glob.1658 return [p.replace('\\', '/') for p in filepaths]1659 else:1660 # use glob output as it is1661 return filepaths1662 def recvScreenshot(self, filename, screenshotSize=(None, None)):1663 ppmfilename = filename + ".ppm"1664 if screenshotSize == (None, None):1665 screenshotSize = self._screenshotSize1666 width, height, zdata = self._agent.eval_in(1667 self._agent_ns, "screenshotZYBGR(%s)" % (repr(screenshotSize),))1668 data = zlib.decompress(zdata)1669 fmbtgti.eye4graphics.wbgr2rgb(data, width, height)1670 if fmbtpng != None:1671 file(filename, "wb").write(1672 fmbtpng.raw2png(data, width, height, 8, "RGB"))1673 else:1674 ppm_header = "P6\n%d %d\n%d\n" % (width, height, 255)1675 f = file(filename + ".ppm", "wb")1676 f.write(ppm_header)1677 f.write(data)1678 f.close()1679 _run([fmbt_config.imagemagick_convert, ppmfilename, filename], expectedExitStatus=[0])1680 os.remove(ppmfilename)1681 return True1682 def recvTopWindowProperties(self):1683 return self.evalPython("topWindowProperties()")1684 def recvWindowProperties(self, window):1685 hwnd = self._window2hwnd(window)1686 return self.evalPython("windowProperties(%s)" % (hwnd,))1687 def recvWindowStatus(self, window):1688 hwnd = self._window2hwnd(window)1689 return self.evalPython("windowStatus(%s)" % (hwnd,))1690 def recvViewData(self, window=None):1691 rv = None1692 if window == None:1693 rv = self.evalPython("topWindowWidgets()")1694 elif isinstance(window, int):1695 rv = self.evalPython("windowWidgets(%s)" % (repr(window),))1696 elif isinstance(window, str) or isinstance(window, unicode):1697 wlist = self.evalPython("windowList()")1698 for w in wlist:1699 if w["title"] == window:1700 rv = self.evalPython("windowWidgets(%s)" % (repr(w["hwnd"]),))1701 break1702 else:1703 raise ValueError('no window with title "%s"' % (window,))1704 else:1705 raise ValueError('illegal window "%s", expected integer or string (hWnd or title)' % (window,))1706 return rv1707 def _parseDumps(self, dumps, dump_suffix, error_template):1708 dumpFilename = self._device.getDumpFilename(dump_suffix) + '.log'1709 error_message = ''1710 rv = []1711 prop_data = {}1712 items = None1713 with open(dumpFilename, 'w') as f:1714 for dump in dumps:1715 f.write(dump + '\n')1716 for line in dump.split('\0'):1717 if line.startswith('!'):1718 error_message = line[1:]1719 continue1720 if line.startswith('#'): # It's a comment / debug output: skip it!1721 continue1722 if line == '[':1723 items = []1724 continue1725 if line == ']':1726 rv.append(items)1727 continue1728 if items is not None:1729 items.append(line)1730 if "=" not in line:1731 continue1732 prop_name, prop_value = line.split("=", 1)1733 if prop_name == "hash" and prop_data:1734 rv.append(prop_data)1735 prop_data = {}1736 prop_data[prop_name] = prop_value.replace(r"\r\n", "\n").replace(r"\\", "\\")1737 if prop_data:1738 rv.append(prop_data)1739 if error_message:1740 raise FMBTWindowsError(error_template % error_message)1741 return rv1742 def recvViewUIAutomation(self, window=None, items=[], properties=None, area=None, walker="raw",1743 filterType="none", filterCondition="", dumpChildClass="", dumpChildName="", doNotDump=False):1744 """returns list of dictionaries, each of which contains properties of1745 an item"""1746 if not walker in ["raw", "control", "content"]:1747 raise ValueError('invalid walker %r' % walker)1748 hwnd = self._window2hwnd(window) if window else None1749 if properties is None:1750 properties = []1751 else:1752 # make sure certain properties are always included1753 properties = list(frozenset(properties) | frozenset(["BoundingRectangle"]))1754 dumps = []1755 if items:1756 for item in items:1757 dumps.append(self.evalPython("dumpUIAutomationElements(%r, %r, %r, %r, %r, %r, %r, %r, %r, %r)" % (1758 hwnd,1759 [str(item.id()) for item in item.branch()],1760 properties,1761 area,1762 walker,1763 filterType,1764 filterCondition,1765 dumpChildClass,1766 dumpChildName,1767 doNotDump)))1768 else:1769 dumps.append(self.evalPython("dumpUIAutomationElements(%r, %r, %r, %r, %r, %r, %r, %r, %r, %r)" % (1770 hwnd,1771 [],1772 properties,1773 area,1774 walker,1775 filterType,1776 filterCondition,1777 dumpChildClass,1778 dumpChildName,1779 doNotDump)))1780 return self._parseDumps(dumps, "dumpUIAutomationElements",1781 "view is not available. An error happened while collecting UI elements with refreshView().\n%s")1782 def sendSetCacheMode(self, mode):1783 dump = self.evalPython("serverSetCacheMode(%r)" % mode)1784 self._parseDumps([dump], "serverSetCacheMode",1785 "An error happened while setting the cache mode.\n%s")1786 def sendClearCache(self):1787 dump = self.evalPython("serverClearCache()")1788 self._parseDumps([dump], "serverClearCache",1789 "An error happened while clearing the cache.\n%s")1790 def sendSetFocus(self, eltHash):1791 dump = self.evalPython("setAutomationElementFocus(%s)" % eltHash)1792 self._parseDumps([dump], "setAutomationElementFocus",1793 "An error happened while setting the focus.\n%s")1794 def sendCollapse(self, eltHash):1795 dump = self.evalPython("AutomationElementCollapse(%s)" % eltHash)1796 self._parseDumps([dump], "AutomationElementCollapse",1797 "An error happened while collapsing the viewitem.\n%s")1798 def sendExpand(self, eltHash):1799 dump = self.evalPython("AutomationElementExpand(%s)" % eltHash)1800 self._parseDumps([dump], "AutomationElementExpand",1801 "An error happened while expanding the viewitem.\n%s")1802 def recvViewCachedItem(self, eltHash):1803 dump = self.evalPython("getCachedAutomationElement(%s)" % eltHash)1804 return self._parseDumps([dump], "getCachedAutomationElement",1805 "viewitem is not available. An error happened while dumping it with cachedElement().\n%s")1806 def recvViewItemPatterns(self, eltHash):1807 dump = self.evalPython("getAutomationElementPatterns(%s)" % eltHash)1808 return self._parseDumps([dump], "getAutomationElementPatterns",1809 "viewitem patterns are not available. An error happened while collecting them with patterns().\n%s")1810 def recvViewItemProperties(self, eltHash):1811 dump = self.evalPython("getAutomationElementProperties(%s)" % eltHash)1812 return self._parseDumps([dump], "getAutomationElementProperties",...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run fMBT automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful