Example #1
0
    def verify(self):
        '''verify UI element is still exist
        '''
        flag = True
        if self.UIAElement == ctypes.POINTER(
                UIA.UIA_wrapper.IUIAutomationElement)():
            flag = False

        try:
            UIAElement = self.UIAElement.FindFirst(
                UIA.UIA_wrapper.TreeScope_Element,
                UIA.IUIAutomation_object.CreateTrueCondition())
        except _ctypes.COMError:
            flag = False
            UIAElement = ctypes.POINTER(UIA.UIA_wrapper.IUIAutomationElement)()

        if UIAElement == ctypes.POINTER(
                UIA.UIA_wrapper.IUIAutomationElement)():
            flag = False

        if not flag:
            LOGGER.warn("Current UIAElement is no longer exist")
            return None

        return UIElement(UIAElement)
Example #2
0
    def _find_by_UIA(self, translated_identifier, scope=UIA.UIA_wrapper.TreeScope_Descendants):
        target_UIAElement = self.UIAElement.FindFirst(scope, translated_identifier)
        if target_UIAElement == ctypes.POINTER(UIA.UIA_wrapper.IUIAutomationElement)():
            LOGGER.debug("Find no element matching identifier")
            return None

        return UIElement(target_UIAElement)
Example #3
0
    def __call__(self, *in_args):
        '''
        For output value, use original value
        For input arguments:
            1. If required argument is an enum, check if input argument fit requirement
            2. If required argument is "POINTER(IUIAutomationElement)", we accept UIElement object,
               get required pointer object from UIElement, and send it to function
            3. Other, no change
        '''
        args = list(in_args)
        if len(self.args) != len(args):
            LOGGER.warn("Input arguments number not match expected")
            return None
        for index, expected_arg in enumerate(self.args):
            expected_arg_type = expected_arg[0]
            if expected_arg_type == "POINTER(IUIAutomationElement)":
                #get the UIAElment
                args[index] = args[index].UIAElement
            elif expected_arg_type in UIA.UIA_enums:
                #enum should be an int value, if argument is a string, should translate to int
                if args[index] in UIA.UIA_enums[expected_arg_type]:
                    args[index] = UIA.UIA_enums[expected_arg_type][args[index]]

                if args[index] not in list(
                        UIA.UIA_enums[expected_arg_type].values()):
                    LOGGER.debug("Input argument not in expected value: %s",
                                 args[index])
                    return None

        return self.function_object(*args)
Example #4
0
    def start(self, **kwargs):
        '''
        get root ready
        like get root element in windows UIA, get browser to target website

        must have a "browser_name" argument in kwargs to indicate which browser to use
        other kwargs are same as normal selenium webdrivers
        '''
        if not "browser_name" in kwargs:
            LOGGER.error("Browser name not specified")
            raise DriverException("Browser name not specified")

        browser_name = kwargs["browser_name"]
        if not browser_name.upper() in self.support_browsers:
            LOGGER.error("Unsupported browser name: %s" , browser_name)
            raise DriverException("Unsupported browser name: %s" % browser_name)

        #remove browser_name key from kwargs
        del kwargs["browser_name"]

        #for ie browser, need to ignore zoom settings
        if browser_name.upper() == "IE":
            if "capabilities" in kwargs:
                #insert "ignoreZoomSetting" in driver capabilities
                caps = kwargs["capabilities"]
                caps["ignoreZoomSetting"] = True
            else:
                #add default capabilities
                caps = DesiredCapabilities.INTERNETEXPLORER
                caps["ignoreZoomSetting"] = True
                kwargs["capabilities"] = caps

        self.webdriver = self.support_browsers[browser_name.upper()](**kwargs)
Example #5
0
    def __init__(self, UIAElement, pattern_identifier):
        self.UIAElement = UIAElement
        self.pattern_object = UIA.get_pattern_by_id(UIAElement,
                                                    pattern_identifier)
        if self.pattern_object is None:
            raise DriverException(
                "Cannot get pattern, stop init pattern object")
        self.methods = {}
        self.properties = {}
        interface_description = UIA.UIA_control_pattern_interfaces[
            pattern_identifier]
        for member_description in interface_description:
            flag, name, args = _unpack(*member_description)
            #do a check, see if member exist in pattern object
            #if not, skip this member
            try:
                getattr(self.pattern_object, name)
            except AttributeError:
                LOGGER.debug("%s not exist in Pattern:%s", name,
                             pattern_identifier)
                continue

            if flag == "method":
                self.methods[name] = args
            elif flag == "property":
                self.properties[name] = args
            else:
                raise DriverException("Unrecognised flag %s" % flag)
Example #6
0
def image_compare(image1, image2, diff_image_name="diff.bmp"):
    '''compare two images, return difference percentage
    #code from http://rosettacode.org/wiki/Percentage_difference_between_images#Python
    '''
    gen_diff_image = image_config.gen_diff_image
    diff_image_location = image_config.diff_image_location

    i1 = Image.open(image1)
    i2 = Image.open(image2)
    assert i1.mode == i2.mode, "Different kinds of images: %s VS %s" % (i1.mode, i2.mode)
    assert i1.size == i2.size, "Different sizes: %s, %s" % (i1.size, i2.size)
    
    #generate diff bitmap
    if gen_diff_image:
        diff = ImageChops.difference(i1, i2)
        diff_image_path = os.path.join(diff_image_location, diff_image_name)
        diff.save(diff_image_path)
        LOGGER.debug("Diff image save to: %s" % diff_image_path)
    
    #caculate the diff percentage
    pairs = zip(i1.getdata(), i2.getdata())
    if len(i1.getbands()) == 1:
        # for gray-scale jpegs
        dif = sum((p1==p2) and 1 or 0 for p1,p2 in pairs)
    else:
        dif = sum((c1==c2) and 1 or 0 for p1,p2 in pairs for c1,c2 in zip(p1,p2))
     
    ncomponents = i1.size[0] * i1.size[1] * 3
    dif_percentage = float(dif) / ncomponents
    LOGGER.debug("Difference (percentage): %f" % dif_percentage)
    return dif_percentage
Example #7
0
    def input(self, *values):
        '''send keyboard input to UI element

        Keyboard input string:
        (1) For normal charactors like [0~9][a~z][A~Z], input directly
        (2) For special charactors like "space", "tab", "newline", "F1~F12"
            You use {key_name} to replace them, all support keys in "selenium/webdriver/common/keys "
        '''
        translated_values = []
        for value in values:
            #still support selenium Keys object
            if isinstance(value, Keys):
                translated_values.append(value)
            elif isinstance(value, int):
                translated_values.append(str(value))
            elif isinstance(value, str):
                #handle special keys
                if re.match("^{.*}$", value) != None:
                    key = value.lstrip("{").rstrip("}")
                    try:
                        key_value = getattr(Keys, key)
                    except AttributeError as e:
                        LOGGER.warning("Input special key not support: %s, skip this input" , key)
                    else:
                        translated_values.append(key_value)
                else:
                    translated_values.append(value)

        self.selenium_element.send_keys(*translated_values)
Example #8
0
    def start(self, **kwargs):
        '''
        get root ready
        like get root element in windows UIA, get browser to target website

        must have a "browser_name" argument in kwargs to indicate which browser to use
        other kwargs are same as normal selenium webdrivers
        '''
        if not "browser_name" in kwargs:
            LOGGER.error("Browser name not specified")
            raise DriverException("Browser name not specified")

        browser_name = kwargs["browser_name"]
        if not browser_name.upper() in self.support_browsers:
            LOGGER.error("Unsupported browser name: %s", browser_name)
            raise DriverException("Unsupported browser name: %s" %
                                  browser_name)

        #remove browser_name key from kwargs
        del kwargs["browser_name"]

        #for ie browser, need to ignore zoom settings
        if browser_name.upper() == "IE":
            if "capabilities" in kwargs:
                #insert "ignoreZoomSetting" in driver capabilities
                caps = kwargs["capabilities"]
                caps["ignoreZoomSetting"] = True
            else:
                #add default capabilities
                caps = DesiredCapabilities.INTERNETEXPLORER
                caps["ignoreZoomSetting"] = True
                kwargs["capabilities"] = caps

        self.webdriver = self.support_browsers[browser_name.upper()](**kwargs)
Example #9
0
    def __call__(self, *in_args):
        '''
        For output value, use original value
        For input arguments:
            1. If required argument is an enum, check if input argument fit requirement
            2. If required argument is "POINTER(IUIAutomationElement)", we accept UIElement object,
               get required pointer object from UIElement, and send it to function
            3. Other, no change
        '''
        args = list(in_args)
        if len(self.args) != len(args):
            LOGGER.warn("Input arguments number not match expected")
            return None
        for index, expected_arg in enumerate(self.args):
            expected_arg_type = expected_arg[0]
            if expected_arg_type == "POINTER(IUIAutomationElement)":
                #get the UIAElment
                args[index] = args[index].UIAElement
            elif expected_arg_type in UIA.UIA_enums:
                #enum should be an int value, if argument is a string, should translate to int
                if args[index] in UIA.UIA_enums[expected_arg_type]:
                    args[index] = UIA.UIA_enums[expected_arg_type][args[index]]

                if args[index] not in list(UIA.UIA_enums[expected_arg_type].values()):
                    LOGGER.debug("Input argument not in expected value: %s" , args[index])
                    return None

        return self.function_object(*args)
Example #10
0
def get_pattern_by_id(UIAElement, pattern_identifier):
    '''get UIA element pattern by identifier, return None if fail
    
    Arguments:
        UIAElement: UIA Element instance
        pattern_identifier: pattern identifier
    Returns:
        pattern instance if success
        None if pattern_identifier not valid or not supported by UIA Element
    '''
    if pattern_identifier in UIA_control_pattern_identifers_mapping:
        UIA_pattern_identifier = UIA_control_pattern_identifers_mapping[pattern_identifier][0]
        UIA_pattern_interface = UIA_control_pattern_identifers_mapping[pattern_identifier][1]
        
        pattern = UIAElement.GetCurrentPatternAs(UIA_pattern_identifier, UIA_pattern_interface._iid_)
        if pattern is None:
            LOGGER.debug("This pattern:%s is not supported by this UIAElment" , pattern_identifier)
            return None
        return ctypes.POINTER(UIA_pattern_interface)(pattern)
        '''
        #Use GetCurrentPatternAs to check if get pattern success
        pattern = UIAElement.GetCurrentPattern(UIA_pattern_identifier).QueryInterface(UIA_pattern_interface)
        return pattern
        '''
    else:
        LOGGER.debug("This pattern identifier is not support: %s, cannot get it from UIA typelib" , pattern_identifier)
        return None
Example #11
0
    def input(self, *values):
        '''send keyboard input to UI element

        Keyboard input string:
        (1) For normal charactors like [0~9][a~z][A~Z], input directly
        (2) For special charactors like "space", "tab", "newline", "F1~F12"
            You use {key_name} to replace them, all support keys in "selenium/webdriver/common/keys "
        '''
        translated_values = []
        for value in values:
            #still support selenium Keys object
            if isinstance(value, Keys):
                translated_values.append(value)
            elif isinstance(value, int):
                translated_values.append(str(value))
            elif isinstance(value, str):
                #handle special keys
                if re.match("^{.*}$", value) != None:
                    key = value.lstrip("{").rstrip("}")
                    try:
                        key_value = getattr(Keys, key)
                    except AttributeError as e:
                        LOGGER.warning(
                            "Input special key not support: %s, skip this input",
                            key)
                    else:
                        translated_values.append(key_value)
                else:
                    translated_values.append(value)

        self.selenium_element.send_keys(*translated_values)
Example #12
0
def get_pattern_by_id(UIAElement, pattern_identifier):
    '''get UIA element pattern by identifier, return None if fail
    
    Arguments:
        UIAElement: UIA Element instance
        pattern_identifier: pattern identifier
    Returns:
        pattern instance if success
        None if pattern_identifier not valid or not supported by UIA Element
    '''
    if pattern_identifier in UIA_control_pattern_identifers_mapping:
        UIA_pattern_identifier = UIA_control_pattern_identifers_mapping[
            pattern_identifier][0]
        UIA_pattern_interface = UIA_control_pattern_identifers_mapping[
            pattern_identifier][1]

        pattern = UIAElement.GetCurrentPatternAs(UIA_pattern_identifier,
                                                 UIA_pattern_interface._iid_)
        if pattern is None:
            LOGGER.debug("This pattern:%s is not supported by this UIAElment",
                         pattern_identifier)
            return None
        return ctypes.POINTER(UIA_pattern_interface)(pattern)
        '''
        #Use GetCurrentPatternAs to check if get pattern success
        pattern = UIAElement.GetCurrentPattern(UIA_pattern_identifier).QueryInterface(UIA_pattern_interface)
        return pattern
        '''
    else:
        LOGGER.debug(
            "This pattern identifier is not support: %s, cannot get it from UIA typelib",
            pattern_identifier)
        return None
Example #13
0
    def find_elements(self, parsed_identifier):
        '''find all matched element
        root find should only find in the first level to avoid search in all UI
        '''
        if parsed_identifier is None:
            translated_identifier = UIA.IUIAutomation_object.CreateTrueCondition(
            )
        else:
            translated_identifier = Translater.ID_Translater(
                parsed_identifier).get_translated()
            if translated_identifier[
                    0] == "Coordinate" or translated_identifier[0] == "Index":
                LOGGER.warn(
                    "find_elements method not support find by Coordinate or find by Index"
                )
                return []
            else:
                translated_identifier = translated_identifier[1]

        scope = UIA.UIA_wrapper.TreeScope_Children
        UIAElementArray = self.UIAElement.FindAll(scope, translated_identifier)
        UIElements = []
        for i in range(UIAElementArray.Length):
            UIElements.append(UIElement(UIAElementArray.GetElement(i)))
        return UIElements
Example #14
0
def image_compare(image1, image2, diff_image_name="diff.bmp"):
    '''compare two images, return difference percentage
    #code from http://rosettacode.org/wiki/Percentage_difference_between_images#Python
    '''
    gen_diff_image = image_config.gen_diff_image
    diff_image_location = image_config.diff_image_location

    i1 = Image.open(image1)
    i2 = Image.open(image2)
    assert i1.mode == i2.mode, "Different kinds of images: %s VS %s" % (
        i1.mode, i2.mode)
    assert i1.size == i2.size, "Different sizes: %s, %s" % (i1.size, i2.size)

    #generate diff bitmap
    if gen_diff_image:
        diff = ImageChops.difference(i1, i2)
        diff_image_path = os.path.join(diff_image_location, diff_image_name)
        diff.save(diff_image_path)
        LOGGER.debug("Diff image save to: %s" % diff_image_path)

    #caculate the diff percentage
    pairs = zip(i1.getdata(), i2.getdata())
    if len(i1.getbands()) == 1:
        # for gray-scale jpegs
        dif = sum((p1 == p2) and 1 or 0 for p1, p2 in pairs)
    else:
        dif = sum((c1 == c2) and 1 or 0 for p1, p2 in pairs
                  for c1, c2 in zip(p1, p2))

    ncomponents = i1.size[0] * i1.size[1] * 3
    dif_percentage = float(dif) / ncomponents
    LOGGER.debug("Difference (percentage): %f" % dif_percentage)
    return dif_percentage
Example #15
0
 def gui_execute(self, command):
     '''execute gui command
     command like "app_map1.app_map2...element1.element2...operation [parameter1 parameter2 ...]"
     '''
     (object_name_list, parameter_list) = gui_command_parser.parse(command, lexer=gui_command_lexer)
     object_= self._get_object_by_name_list(object_name_list)
     LOGGER.debug("GUI execute %s %s" , object_name_list, parameter_list)
     object_(*parameter_list)
Example #16
0
 def run(self):
     if self.type == "GUI":
         LOGGER.debug("run gui command: %s" , self.command)
         self.app_map.gui_execute(self.command)
     elif self.type == "CLI":
         LOGGER.debug("run cli command: %s" , self.command)
         self.app_map.cli_execute(self.command)
     else:
         raise ValueError("step type must be GUI or CLI, get: %s" % self.type)
Example #17
0
 def _translated_atomic_identifier(self, parsed_atomic_id):
     if parsed_atomic_id[0] in UIA.UIA_automation_element_property_identifers_mapping:
         return UIA.IUIAutomation_object.CreatePropertyCondition(UIA.UIA_automation_element_property_identifers_mapping[parsed_atomic_id[0]], parsed_atomic_id[1])
     elif parsed_atomic_id[0] in UIA.UIA_control_pattern_property_identifiers_mapping:
         return UIA.IUIAutomation_object.CreatePropertyCondition(UIA.UIA_control_pattern_property_identifiers_mapping[parsed_atomic_id[0]], parsed_atomic_id[1])
     else:
         #use no UIA identifier will be skipped
         LOGGER.warn("identifier: %s not in UIA property maps" , parsed_atomic_id[0])
         return None
Example #18
0
 def drag_drop(self, abs_source_coords, abs_dest_coords):
     '''Move: move mouse from source_coords to dest_coords
     mouse drag drop is not related with UI element
     so need use abs coords
     '''
     LOGGER.debug("Mouse drag drop from: %s to %s" , repr(abs_source_coords), repr(abs_dest_coords))
     self.UIElement.set_focus()
     SendMouseInput(abs_source_coords, button_down=True, button_up=False)
     self.Move(abs_source_coords, abs_dest_coords)
     SendMouseInput(abs_dest_coords, button_down=False, button_up=True)
Example #19
0
 def gui_execute(self, command):
     '''execute gui command
     command like "app_map1.app_map2...element1.element2...operation [parameter1 parameter2 ...]"
     '''
     (object_name_list,
      parameter_list) = gui_command_parser.parse(command,
                                                 lexer=gui_command_lexer)
     object_ = self._get_object_by_name_list(object_name_list)
     LOGGER.debug("GUI execute %s %s", object_name_list, parameter_list)
     object_(*parameter_list)
Example #20
0
 def drag_drop(self, abs_source_coords, abs_dest_coords):
     '''Move: move mouse from source_coords to dest_coords
     mouse drag drop is not related with UI element
     so need use abs coords
     '''
     LOGGER.debug("Mouse drag drop from: %s to %s", repr(abs_source_coords),
                  repr(abs_dest_coords))
     self.UIElement.set_focus()
     SendMouseInput(abs_source_coords, button_down=True, button_up=False)
     self.Move(abs_source_coords, abs_dest_coords)
     SendMouseInput(abs_dest_coords, button_down=False, button_up=True)
Example #21
0
 def verification(self):
     '''verify the app map xml using according schema, need pyxb module
     '''
     try:
         import pyxb
     except ImportError:
         LOGGER.debug("pyxb not install, skip app map verification")
         return
         
     from .validate import check_app_map
     check_app_map(core_config.query_schema_file("AXUI_app_map.xsd"), self.app_map_xml)
Example #22
0
    def _find_by_UIA(self,
                     translated_identifier,
                     scope=UIA.UIA_wrapper.TreeScope_Descendants):
        target_UIAElement = self.UIAElement.FindFirst(scope,
                                                      translated_identifier)
        if target_UIAElement == ctypes.POINTER(
                UIA.UIA_wrapper.IUIAutomationElement)():
            LOGGER.debug("Find no element matching identifier")
            return None

        return UIElement(target_UIAElement)
Example #23
0
 def find_element(self, parsed_identifier):
     '''
     find the first child UI element via identifier, return one UIAElement if success, return None if not find
     '''
     translated_identifier = Translater.ID_Translater(parsed_identifier).get_translated()
     try:
         selenium_element = self.selenium_element.find_element(by=translated_identifier[0], value=translated_identifier[1])
     except NoSuchElementException:
         LOGGER.debug("Cannot find target element")
         return None
     else:
         return UIElement(selenium_element)
Example #24
0
    def verification(self):
        '''verify the app map xml using according schema, need pyxb module
        '''
        try:
            import pyxb
        except ImportError:
            LOGGER.debug("pyxb not install, skip app map verification")
            return

        from .validate import check_app_map
        check_app_map(core_config.query_schema_file("AXUI_app_map.xsd"),
                      self.app_map_xml)
Example #25
0
    def set_focus(self):
        '''set foucs this element

        Will bring this element to the front, used by Keyboard, Mouse, Touch

        Arguments:
        Returns:
        '''
        try:
            self.UIAElement.SetFocus()
        except _ctypes.COMError:
            LOGGER.warn("SetFocus fail on current element, maybe due to this element not support SetFocus")
Example #26
0
def get_driver():
    '''get driver
    Return: return driver module selected in config
    '''
    try:
        import sys, os
        sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
        driver = __import__(driver_config.driver_used + "_driver")
    except ImportError as e:
        LOGGER.error("Driver load error: %s" % driver_config.driver_used)
        raise e

    return driver
Example #27
0
def get_driver():
    '''get driver
    Return: return driver module selected in config
    '''
    try:
        import sys, os
        sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
        driver = __import__(driver_config.driver_used+"_driver")
    except ImportError as e:
        LOGGER.error("Driver load error: %s" % driver_config.driver_used)
        raise e
        
    return driver
Example #28
0
    def move(self, abs_source_coords, abs_dest_coords):
        '''Move: move mouse from source_coords to dest_coords
        mouse move is not related with UI element
        so need use abs coords
        '''
        import time
        import random
        x_range = abs(abs_source_coords[0] - abs_dest_coords[0])
        y_range = abs(abs_source_coords[1] - abs_dest_coords[1])
        x_sample_size = x_range / 10
        y_sample_size = y_range / 10
        #choose the bigger one
        sample_size = x_sample_size > y_sample_size and x_sample_size or y_sample_size
        #build population
        if abs_source_coords[0] < abs_dest_coords[0]:
            x_population = list(range(abs_source_coords[0],
                                      abs_dest_coords[0]))
        else:
            x_population = list(range(abs_dest_coords[0],
                                      abs_source_coords[0]))
        while len(x_population) < sample_size:
            x_population = x_population * 2

        if abs_source_coords[1] < abs_dest_coords[1]:
            y_population = list(range(abs_source_coords[1],
                                      abs_dest_coords[1]))
        else:
            y_population = list(range(abs_dest_coords[1],
                                      abs_source_coords[1]))
        while len(y_population) < sample_size:
            y_population = y_population * 2
        #get coords
        if abs_source_coords[0] < abs_dest_coords[0]:
            x_coords = sorted(random.sample(x_population, sample_size))
        else:
            x_coords = sorted(random.sample(x_population, sample_size),
                              reverse=True)
        if abs_source_coords[1] < abs_dest_coords[1]:
            y_coords = sorted(random.sample(y_population, sample_size))
        else:
            y_coords = sorted(random.sample(y_population, sample_size),
                              reverse=True)
        #move mouse
        LOGGER.debug("Mouse move from: %s to %s", repr(abs_source_coords),
                     repr(abs_dest_coords))
        self.UIElement.set_focus()
        for i in range(sample_size):
            SendMouseInput([x_coords[i], y_coords[i]],
                           button_down=False,
                           button_up=False)
            time.sleep(0.1)
Example #29
0
    def set_focus(self):
        '''set foucs this element

        Will bring this element to the front, used by Keyboard, Mouse, Touch

        Arguments:
        Returns:
        '''
        try:
            self.UIAElement.SetFocus()
        except _ctypes.COMError:
            LOGGER.warn(
                "SetFocus fail on current element, maybe due to this element not support SetFocus"
            )
Example #30
0
 def find_element(self, parsed_identifier):
     '''
     find the first child UI element via identifier, return one UIAElement if success, return None if not find
     '''
     translated_identifier = Translater.ID_Translater(
         parsed_identifier).get_translated()
     try:
         selenium_element = self.selenium_element.find_element(
             by=translated_identifier[0], value=translated_identifier[1])
     except NoSuchElementException:
         LOGGER.debug("Cannot find target element")
         return None
     else:
         return UIElement(selenium_element)
Example #31
0
 def _translated_atomic_identifier(self, parsed_atomic_id):
     if parsed_atomic_id[
             0] in UIA.UIA_automation_element_property_identifers_mapping:
         return UIA.IUIAutomation_object.CreatePropertyCondition(
             UIA.UIA_automation_element_property_identifers_mapping[
                 parsed_atomic_id[0]], parsed_atomic_id[1])
     elif parsed_atomic_id[
             0] in UIA.UIA_control_pattern_property_identifiers_mapping:
         return UIA.IUIAutomation_object.CreatePropertyCondition(
             UIA.UIA_control_pattern_property_identifiers_mapping[
                 parsed_atomic_id[0]], parsed_atomic_id[1])
     else:
         #use no UIA identifier will be skipped
         LOGGER.warn("identifier: %s not in UIA property maps",
                     parsed_atomic_id[0])
         return None
Example #32
0
 def get_translated(self):
     '''
     get translated result from parsed identifier
     '''
     if len(self.parsed_identifier) == 2:
         name = self.parsed_identifier[0]
         value = self.parsed_identifier[1]
         try:
             getattr(MobileBy, name.upper())
         except AttributeError:
             LOGGER.error("identifier not support: %s" , name)
             raise DriverException("identifier not support: %s" % name)
         return getattr(MobileBy, name.upper()), value
     else:
         LOGGER.error("Get error parsed_id: %s" , repr(self.parsed_identifier))
         raise DriverException("Get error parsed_id: %s" % repr(self.parsed_identifier))
Example #33
0
    def _find_by_index(self, translated_identifier, scope=UIA.UIA_wrapper.TreeScope_Descendants):
        if isinstance(translated_identifier, tuple) and len(translated_identifier) == 2:
            identifier = translated_identifier[0]
            index = translated_identifier[1]
        elif isinstance(translated_identifier, int):
            identifier = UIA.IUIAutomation_object.CreateTrueCondition()
            index = translated_identifier
        else:
            LOGGER.warn("Index identifier is wrong, get %s" , repr(translated_identifier))
            return None

        target_UIAElements = self.UIAElement.FindAll(scope, identifier)
        if index+1 > target_UIAElements.Length:
            LOGGER.warn("Find %d matched elements, index:%d out of range", target_UIAElements.Length, index)
            return None
        return UIElement(target_UIAElements.GetElement(index))
Example #34
0
    def screenshot(self, screenshot_location=""):
        '''take a screen shot for this element
        '''
        if not os.path.isdir(screenshot_location):
            screenshot_location = self.screenshot_location

        self.start()

        filename = self.name + "_" + str(time.time()) + ".bmp"
        absfile = os.path.join(screenshot_location, filename)
        if os.path.isfile(absfile):
            os.remove(absfile)

        self.UIElement.screenshot(absfile)
        LOGGER.info("Screenshot taken: %s", absfile)
        return absfile
Example #35
0
    def right_click(self, relative_coords=None):
        '''RightClick: right click the UI element, or taget coords
        Arguments:
            coords: coordinate indicate where mouse click, default use UI element click point
        Returns:
        '''
        if relative_coords is None:
            coords = self.UIElement.get_clickable_point()
        else:
            coords = [0, 0]
            coords[0] = relative_coords[0] + self.UIElement.coordinate[0]
            coords[1] = relative_coords[1] + self.UIElement.coordinate[1]

        LOGGER.debug("Mouse right click at: %s", repr(coords))
        self.UIElement.set_focus()
        SendMouseInput(coords, button="right")
Example #36
0
 def right_click(self, relative_coords = None):
     '''RightClick: right click the UI element, or taget coords
     Arguments:
         coords: coordinate indicate where mouse click, default use UI element click point
     Returns:
     '''
     if relative_coords is None:
         coords = self.UIElement.get_clickable_point()
     else:
         coords = [0, 0]
         coords[0] = relative_coords[0]+self.UIElement.coordinate[0]
         coords[1] = relative_coords[1]+self.UIElement.coordinate[1]
     
     LOGGER.debug("Mouse right click at: %s" , repr(coords))
     self.UIElement.set_focus()
     SendMouseInput(coords, button="right")
Example #37
0
    def cli_execute(self, command):
        '''execute cli command
        command like "app parameter1 parameter 2"
        may contain variables
        '''
        args = cli_command_parser.parse(command, lexer=cli_command_lexer)
        #replace variables
        for i, arg in enumerate(args):
            if not re.match("^{.*}$", arg) is None:
                args[i] = self.variables[arg.strip("{").strip("}")]

        #some app need to execute in their folder
        app_path = os.path.dirname(args[0])
        if app_path:
            os.chdir(app_path)

        LOGGER.debug("CLI execute: %s", repr(args))
        p = subprocess.Popen(args, shell=True)
Example #38
0
 def cli_execute(self, command):
     '''execute cli command
     command like "app parameter1 parameter 2"
     may contain variables
     '''
     args = cli_command_parser.parse(command, lexer=cli_command_lexer)
     #replace variables
     for i, arg in enumerate(args):
         if not re.match("^{.*}$", arg) is None:
             args[i] = self.variables[arg.strip("{").strip("}")]
             
     #some app need to execute in their folder
     app_path = os.path.dirname(args[0])
     if app_path:
         os.chdir(app_path)
             
     LOGGER.debug("CLI execute: %s" , repr(args))
     p = subprocess.Popen(args, shell=True)
Example #39
0
    def _wait_stop(self):
        '''wait until UIElement is not valid or timeout
        '''
        LOGGER.info("Waiting Element to stop, timeout %s" % self.timeout)
        if not self.identifier is None:
            #keep verify the element, until not found or timeout
            start_time = time.time()
            while True:
                self.UIElement = self.verify()
                if self.UIElement is None:
                    return

                time.sleep(0.1)
                current_time = time.time()
                if current_time - start_time > self.timeout:
                    raise TimeOutError(
                        "time out encounter, during stop element:%s" %
                        self.name)
Example #40
0
 def get_translated(self):
     '''
     get translated result from parsed identifier
     '''
     if len(self.parsed_identifier) == 2:
         name = self.parsed_identifier[0]
         value = self.parsed_identifier[1]
         try:
             getattr(By, name.upper())
         except AttributeError:
             LOGGER.error("identifier not support: %s", name)
             raise DriverException("identifier not support: %s" % name)
         return getattr(By, name.upper()), value
     else:
         LOGGER.error("Get error parsed_id: %s",
                      repr(self.parsed_identifier))
         raise DriverException("Get error parsed_id: %s" %
                               repr(self.parsed_identifier))
Example #41
0
 def move(self, abs_source_coords, abs_dest_coords):
     '''Move: move mouse from source_coords to dest_coords
     mouse move is not related with UI element
     so need use abs coords
     '''
     import time
     import random
     x_range = abs(abs_source_coords[0] - abs_dest_coords[0])
     y_range = abs(abs_source_coords[1] - abs_dest_coords[1])
     x_sample_size = x_range/10
     y_sample_size = y_range/10
     #choose the bigger one
     sample_size = x_sample_size > y_sample_size and x_sample_size or y_sample_size
     #build population
     if abs_source_coords[0] < abs_dest_coords[0]:
         x_population = list(range(abs_source_coords[0], abs_dest_coords[0]))
     else:
         x_population = list(range(abs_dest_coords[0], abs_source_coords[0]))
     while len(x_population)<sample_size:
         x_population = x_population*2
         
     if abs_source_coords[1] < abs_dest_coords[1]:
         y_population = list(range(abs_source_coords[1], abs_dest_coords[1]))
     else:
         y_population = list(range(abs_dest_coords[1], abs_source_coords[1]))
     while len(y_population)<sample_size:
         y_population = y_population*2
     #get coords
     if abs_source_coords[0] < abs_dest_coords[0]:
         x_coords = sorted(random.sample(x_population, sample_size))
     else:
         x_coords = sorted(random.sample(x_population, sample_size), reverse=True)
     if abs_source_coords[1] < abs_dest_coords[1]:
         y_coords = sorted(random.sample(y_population, sample_size))
     else:
         y_coords = sorted(random.sample(y_population, sample_size), reverse=True)
     #move mouse
     LOGGER.debug("Mouse move from: %s to %s" , repr(abs_source_coords), repr(abs_dest_coords))
     self.UIElement.set_focus()
     for i in range(sample_size):
         SendMouseInput([x_coords[i], y_coords[i]], button_down=False, button_up=False)
         time.sleep(0.1)
Example #42
0
    def find_elements(self, parsed_identifier):
        '''find all matched element
        root find should only find in the first level to avoid search in all UI
        '''
        if parsed_identifier is None:
            translated_identifier = UIA.IUIAutomation_object.CreateTrueCondition()
        else:
            translated_identifier = Translater.ID_Translater(parsed_identifier).get_translated()
            if translated_identifier[0] == "Coordinate" or translated_identifier[0] == "Index":
                LOGGER.warn("find_elements method not support find by Coordinate or find by Index")
                return []
            else:
                translated_identifier = translated_identifier[1]

        scope = UIA.UIA_wrapper.TreeScope_Children
        UIAElementArray = self.UIAElement.FindAll(scope, translated_identifier)
        UIElements = []
        for i in range(UIAElementArray.Length):
            UIElements.append(UIElement(UIAElementArray.GetElement(i)))
        return UIElements
Example #43
0
def screenshot(filename, coordinate=None):
    '''screenshot for target UI area
    
    parameters:
        handle:      window handler for target UI
        filename:    screenshot filename, should be .bmp file
        coordinate:  (left, top, right, bottom) coordinate for target area
    '''
    current_dir = os.path.dirname(__file__)
    screenshot_app = os.path.join(current_dir, "screenshot.exe")

    if coordinate is None:
        cmd = '"%s" -f %s' % (screenshot_app, filename)
    else:
        cmd = '"%s" -f %s -l %s -t %s -r %s -b %s' %\
               (screenshot_app, filename, coordinate[0], coordinate[1], coordinate[2], coordinate[3])

    LOGGER.debug("screenshot command: %s", cmd)
    process = subprocess.Popen(cmd)

    return process.wait()
Example #44
0
    def verify(self):
        '''verify UI element is still exist
        '''
        flag = True
        if self.UIAElement == ctypes.POINTER(UIA.UIA_wrapper.IUIAutomationElement)():
            flag = False

        try:
            UIAElement = self.UIAElement.FindFirst(UIA.UIA_wrapper.TreeScope_Element, UIA.IUIAutomation_object.CreateTrueCondition())
        except _ctypes.COMError:
            flag = False
            UIAElement = ctypes.POINTER(UIA.UIA_wrapper.IUIAutomationElement)()

        if UIAElement == ctypes.POINTER(UIA.UIA_wrapper.IUIAutomationElement)():
            flag = False

        if not flag:
            LOGGER.warn("Current UIAElement is no longer exist")
            return None

        return UIElement(UIAElement)
Example #45
0
def screenshot(filename, coordinate=None):
    '''screenshot for target UI area
    
    parameters:
        handle:      window handler for target UI
        filename:    screenshot filename, should be .bmp file
        coordinate:  (left, top, right, bottom) coordinate for target area
    '''
    current_dir = os.path.dirname(__file__)
    screenshot_app = os.path.join(current_dir, "screenshot.exe")
    
    if coordinate is None:
        cmd = '"%s" -f %s' % (screenshot_app, filename)
    else:
        cmd = '"%s" -f %s -l %s -t %s -r %s -b %s' %\
               (screenshot_app, filename, coordinate[0], coordinate[1], coordinate[2], coordinate[3])
        
    LOGGER.debug("screenshot command: %s" , cmd)
    process = subprocess.Popen(cmd)
    
    return process.wait()
Example #46
0
    def _find_by_index(self,
                       translated_identifier,
                       scope=UIA.UIA_wrapper.TreeScope_Descendants):
        if isinstance(translated_identifier,
                      tuple) and len(translated_identifier) == 2:
            identifier = translated_identifier[0]
            index = translated_identifier[1]
        elif isinstance(translated_identifier, int):
            identifier = UIA.IUIAutomation_object.CreateTrueCondition()
            index = translated_identifier
        else:
            LOGGER.warn("Index identifier is wrong, get %s",
                        repr(translated_identifier))
            return None

        target_UIAElements = self.UIAElement.FindAll(scope, identifier)
        if index + 1 > target_UIAElements.Length:
            LOGGER.warn("Find %d matched elements, index:%d out of range",
                        target_UIAElements.Length, index)
            return None
        return UIElement(target_UIAElements.GetElement(index))
Example #47
0
def get_property_by_id(UIAElement, property_identifier):
    '''get UIA element property by identifier, return None if fail
    
    Arguments:
        UIAElement: UIA Element instance
        property_identifier: property identifier
    Returns:
        property_value if success
        None if property_identifier not valid or not supported by UIA Element
    '''
    if property_identifier in UIA_automation_element_property_identifers_mapping:
        property_value = UIAElement.GetCurrentPropertyValue(
            UIA_automation_element_property_identifers_mapping[
                property_identifier])
        if property_value is None:
            LOGGER.debug("This property:%s is not supported by this UIAElment",
                         property_identifier)
            return ""
        return property_value

    elif property_identifier in UIA_control_pattern_availability_property_identifiers_mapping:
        property_value = UIAElement.GetCurrentPropertyValue(
            UIA_control_pattern_availability_property_identifiers_mapping[
                property_identifier])
        if property_value is None:
            LOGGER.debug("This property:%s is not supported by this UIAElment",
                         property_identifier)
            return ""
        return property_value
    else:
        LOGGER.debug(
            "This property identifier is not support: %s, cannot get it from UIA typelib"
            % property_identifier)
        return None
Example #48
0
def get_property_by_id(UIAElement, property_identifier):
    '''get UIA element property by identifier, return None if fail
    
    Arguments:
        UIAElement: UIA Element instance
        property_identifier: property identifier
    Returns:
        property_value if success
        None if property_identifier not valid or not supported by UIA Element
    '''
    if property_identifier in UIA_automation_element_property_identifers_mapping:
        property_value = UIAElement.GetCurrentPropertyValue(UIA_automation_element_property_identifers_mapping[property_identifier])
        if property_value is None:
            LOGGER.debug("This property:%s is not supported by this UIAElment" , property_identifier)
            return ""
        return property_value
        
    elif property_identifier in UIA_control_pattern_availability_property_identifiers_mapping:
        property_value = UIAElement.GetCurrentPropertyValue(UIA_control_pattern_availability_property_identifiers_mapping[property_identifier])
        if property_value is None:
            LOGGER.debug("This property:%s is not supported by this UIAElment" , property_identifier)
            return ""
        return property_value
    else:
        LOGGER.debug("This property identifier is not support: %s, cannot get it from UIA typelib" % property_identifier)
        return None
Example #49
0
    def _wait_start(self):
        '''wait until UIElement is valid or timeout
        '''
        #keep finding the element by identifier, until found or timeout
        LOGGER.info("Waiting Element show up, timeout %s", self.timeout)
        start_time = time.time()
        while True:
            current_time = time.time()
            self.UIElement = self.verify()
            if not self.UIElement is None:
                LOGGER.info("Find element: %s after waiting %ss, continue",
                            self.name, current_time - start_time)
                #do a desktop screenshot here as required
                if self.screenshot_on:
                    #get root
                    element = self
                    parent = element.parent
                    while not parent is None:
                        element = parent
                        parent = element.parent
                    #screenshot
                    element.screenshot()
                return

            time.sleep(0.1)
            if current_time - start_time > self.timeout:
                #do a desktop screenshot here as required
                if not self.screenshot_off:
                    #get root
                    element = self
                    parent = element.parent
                    while not parent is None:
                        element = parent
                        parent = element.parent
                    #screenshot
                    element.screenshot()
                raise TimeOutError(
                    "time out encounter, during start element:%s" % self.name)
Example #50
0
    def __init__(self, UIAElement, pattern_identifier):
        self.UIAElement = UIAElement
        self.pattern_object = UIA.get_pattern_by_id(UIAElement, pattern_identifier)
        if self.pattern_object is None:
            raise DriverException("Cannot get pattern, stop init pattern object")
        self.methods = {}
        self.properties = {}
        interface_description = UIA.UIA_control_pattern_interfaces[pattern_identifier]
        for member_description in interface_description:
            flag, name, args = _unpack(*member_description)
            #do a check, see if member exist in pattern object
            #if not, skip this member
            try:
                getattr(self.pattern_object, name)
            except AttributeError:
                LOGGER.debug("%s not exist in Pattern:%s", name, pattern_identifier)
                continue

            if flag == "method":
                self.methods[name] = args
            elif flag == "property":
                self.properties[name] = args
            else:
                raise DriverException("Unrecognised flag %s" % flag)
Example #51
0
def check_app_map(XSD_file, app_map_file):
    XSD_module_name = os.path.basename(XSD_file).split(".")[0]
    XSD_module_dir = os.path.dirname(XSD_file)
    generate_module(XSD_file, XSD_module_name, XSD_module_dir)

    sys.path.insert(0, XSD_module_dir)
    XSD_module = __import__(XSD_module_name)

    with open(app_map_file) as app_map:
        try:
            XSD_module.CreateFromDocument(app_map.read())
            LOGGER.debug("Check successful")
        except pyxb.UnrecognizedContentError as e:
            LOGGER.warn(e.details())
        except pyxb.IncompleteElementContentError as e:
            LOGGER.warn(e.details())
        except pyxb.ValidationError as e:
            LOGGER.warn(e.details())
Example #52
0
def check_app_map(XSD_file, app_map_file):
    XSD_module_name = os.path.basename(XSD_file).split(".")[0]
    XSD_module_dir = os.path.dirname(XSD_file)
    generate_module(XSD_file, XSD_module_name, XSD_module_dir)
    
    sys.path.insert(0, XSD_module_dir)
    XSD_module = __import__(XSD_module_name)

    with open(app_map_file) as app_map:
        try:
            XSD_module.CreateFromDocument(app_map.read())
            LOGGER.debug("Check successful")
        except pyxb.UnrecognizedContentError as e:
            LOGGER.warn(e.details())
        except pyxb.IncompleteElementContentError as e:
            LOGGER.warn(e.details())
        except pyxb.ValidationError as e:
            LOGGER.warn(e.details())
Example #53
0
 def get_property(self, name):
     '''
     get property value
     '''
     try:
         obj = getattr(self.selenium_element, name)
     except AttributeError:
         LOGGER.debug("Cannot find this attribute: %s", name)
         if hasattr(self.selenium_element, "get_attribute"):
             LOGGER.debug("Try get_attribute method")
             return self.selenium_element.get_attribute(name)
     else:
         if inspect.ismethod(obj):
             LOGGER.debug("This is a method, not a property: %s", name)
             return None
         else:
             return obj
Example #54
0
 def start(self):
     '''start and find this UIElement
     '''
     #need to start parent element first
     self.parent.start()
     if self.verify() is None:
         LOGGER.info(
             "Start function triggered, due to cannot find element: %s",
             self.name)
         #run start func
         if self.start_func:
             self.start_func.run()
         else:
             LOGGER.info("Element doesn't have start function")
         self._wait_start()
     else:
         LOGGER.info("Find element: %s, continue", self.name)
Example #55
0
 def get_property(self, name):
     '''
     get property value
     '''
     try:
         obj = getattr(self.selenium_element, name)
     except AttributeError:
         LOGGER.debug("Cannot find this attribute: %s" , name)
         if hasattr(self.selenium_element, "get_attribute"):
             LOGGER.debug("Try get_attribute method")
             return self.selenium_element.get_attribute(name)
     else:
         if inspect.ismethod(obj):
             LOGGER.debug("This is a method, not a property: %s" , name)
             return None
         else:
             return obj
Example #56
0
 def input(self, *values):
     '''take a string, translate to win32 event, and input to system
     Arguments:
         string: a string represent the keys input
         pause: global pause time during each key input, default to 0.05s
     Returns:
     
     Keyboard input string introduce:
     (1) For normal charactors like [0~9][a~z][A~Z], input directly
     (2) For special charactors like "space", "tab", "newline", "F1~F12"
         You use {key_name} to replace them
         Here are the support key list:
         backspace       :       {BACK}, {BACKSPACE}, {BKSP}, {BS}
         break           :       {BREAK}
         capslock        :       {CAP}, {CAPSLOCK}
         delete          :       {DEL}, {DELETE}
         down            :       {DOWN}
         end             :       {END}
         enter           :       {ENTER}
         ESC             :       {ESC}
         F1~F24          :       {F1}~{F24}
         help            :       {HELP}
         home            :       {HOME}
         insert          :       {INS}, {INSERT}
         left            :       {LEFT}
         left windows    :       {LWIN}
         number lock     :       {NUMLOCK}
         page down       :       {PGDN}
         page up         :       {PGUP}
         print screen    :       {PRTSC}
         right           :       {RIGHT}
         right menu      :       {RMENU}
         right windows   :       {RWIN}
         scroll lock     :       {SCROLLLOCK}
         space           :       {SPACE}
         tab             :       {TAB}
         up              :       {UP}
     (3) For key combinations
         ctrl+X          :       {CTRL+X}
         shift+X         :       {SHIFT+X}
         menu+X          :       {MENU+X}
         windows key+X   :       {LWIN+X}
         ctrl+shift+X    :       {CTRL+SHIFT+X}
         ctrl+(XYZ)      :       {CTRL+XYZ}
     '''
     #set focus before input keys
     self.UIElement.set_focus()
     
     #translate arguments to a string
     LOGGER.debug("Before translate, value: %s" , repr(values))
     string = ""
     for value in values:
         #value should only allow to be string or int
         if isinstance(value, int):
             translated_value = str(value)
             string += translated_value
         elif isinstance(value, str):
             if re.match("^{\+*}$", value) != None:
                 #for key combinations, we need to do some translation
                 #like "{CTRL+A}" to "^A", "{CTRL+SHIFT+B}" to "^+B"
                 keys = value.lstrip("{").rstrip("}").split("+")
                 for key in keys:
                     if key.upper() in self.key_combinations:
                         translated_value += self.key_combinations[key.upper()]
                     else:
                         translated_value += "("+key+")"
             else:
                 translated_value = value
             
             string += translated_value
         else:
             LOGGER.warning("keyboard input method arguments can only be string or int value, other value will be skipped")
             
     LOGGER.debug("Translated string: %s" , string)
     
     keys = parse_keys(string)
     LOGGER.debug("Keyboard input string: %s, parsed keys: %s" , string, repr(keys))
     for k in keys:
         k.Run()
         time.sleep(0.05)
Example #57
0
#set DPI awareness for win8.1 and win10
from AXUI.logger import LOGGER
import subprocess
p = subprocess.Popen("wmic path win32_operatingsystem get version", stdout=subprocess.PIPE)
(stdout, stderr) = p.communicate()
windows_version = stdout.split()[1]
LOGGER.debug("Windows verison: %s" , windows_version)
#need set DPI awareness for win8.1 and win10
if (int(windows_version.split(".")[0]) >= 6 and int(windows_version.split(".")[1]) >= 3) \
    or int(windows_version.split(".")[0]) >= 10:
    LOGGER.debug("Set DPI awareness for windows verison: %s" , windows_version)
    import ctypes
    shcore = ctypes.windll.shcore
    shcore.SetProcessDpiAwareness(2)
    
from .UIElement import UIElement, Root
Example #58
0
def t_error(t):
    LOGGER.debug("Illegal character %s in Ln: %d" , repr(t.value[0]), t.lexer.lineno)
    raise Exception("")
    t.lexer.skip(1)
Example #59
0
def p_error(p):
    LOGGER.debug("Syntax error in input: %s, Ln: %d" , repr(p.value), p.lineno)
    raise Exception("")