示例#1
0
 def is_window_content_accessible(self):
     """Checks if the application is alive its window content is accessible"""
     get_elements_apple_script = \
         'tell application "{sys_app}" to tell front window of application process "{app_name}" to return entire ' \
         'contents'.format(sys_app=self.system_level_application_name, app_name=self.get_application_process_name())
     objects_list = run_apple_script(get_elements_apple_script)
     return bool(objects_list)
示例#2
0
    def click_by_title(self, title, timeout=60, use_cache=True):
        """Clicks on an object by its title / text / name. Trying twice as default.

        :param title: Title / text / name
        :param timeout: Timeout in seconds for object to appear
        :param use_cache: Try first on the last known location of the requested element
        :return: True if success
        """
        start_time = time.time()
        estimated_end_time = start_time + timeout
        obj = self.wait_for_element(title=title,
                                    timeout=timeout,
                                    use_cache=True)
        if not obj:
            return False
        cmd = 'tell application "{sys_app_name}" to click {xtype} "{xvalue}" {xpath}'.format(
            sys_app_name=self.system_level_application_name,
            xtype=obj.type,
            xvalue=obj.value,
            xpath=obj.path)
        time.sleep(1)
        logger.debug('Trying to click on {cmd}'.format(cmd=cmd))
        result = run_apple_script(cmd)
        if not result:
            if use_cache:
                # We want to try again without cache:
                # 1. Its possible that because of cache we are trying to press a ghost element
                # 2. We want to try again to eliminate mac voodoo (Didn't load, Didn't respond, etc..)
                return self.click_by_title(title=title,
                                           timeout=int(estimated_end_time -
                                                       time.time()),
                                           use_cache=False)
            else:
                return False
        return True
示例#3
0
 def is_running(self):
     """Returns True if the application is running"""
     app_name = self.application_process_name if self.get_application_process_name(
     ) else self.app_name
     cmd = 'tell application "{sys_app_name}" to (name of processes) contains "{app_name}"'.format(
         sys_app_name=self.system_level_application_name, app_name=app_name)
     time.sleep(1)
     result = run_apple_script(cmd).strip()
     return result == 'true'
示例#4
0
 def get_window_position(self):
     """Returns a tuple with the window (x,y) position"""
     cmd = 'tell application "{sys_app_name}" to return position of window 1 of application process' \
           ' "{app_name}"'.format(sys_app_name=self.system_level_application_name,
                                  app_name=self.get_application_process_name())
     result = run_apple_script(cmd)
     if result:
         pos_x = result.split(",")[0].strip()
         pos_y = result.split(",")[-1].split("\n")[0].strip()
         return pos_x, pos_y
示例#5
0
 def get_application_process_name(self):
     if not self.application_process_name:
         get_application_process_name_script = \
             'tell application "{sys_app}" \n set application_id to (get the id of application "{app_name}" as ' \
             'string) \n set process_name to name of (application processes where bundle identifier is ' \
             'application_id) \n end tell'.format(sys_app=self.system_level_application_name, app_name=self.app_name)
         name = run_apple_script(
             get_application_process_name_script).strip()
         if name:
             logger.debug('Application process name is: {}'.format(name))
             self.application_process_name = name
     return self.application_process_name
示例#6
0
    def set_element_value(self, element_role, element_position_path,
                          new_value):
        """Set value of element_role of element_position_path to new_value

        :param element_role: The element role like "button"
        :param element_position_path: The element position inside the application view
        :param new_value: The new requested value
        :return: True if successful
        """
        cmd = '''on run {}
                tell application "''' + self.system_level_application_name + '''"
                tell application process "''' + self.get_application_process_name(
        ) + '''"
                set value of ''' + element_role + ''' of ''' + element_position_path + ''' to "''' + new_value + '''"
                end tell
                end tell
                end run'''
        result = run_apple_script(cmd)
        return bool(result)
示例#7
0
 def get_text_position(self, text):
     """Return the position of a text in the application (upper left corner)
     :param text: Text to locate
     :return: (pos_x, pos_y)
     """
     obj = self.wait_for_element(title=text)
     if not obj:
         return False
     cmd = 'tell application "{sys_app_name}" to return position of {xtype} "{xvalue}" {xpath}'.format(
         sys_app_name=self.system_level_application_name,
         xtype=obj.type,
         xvalue=obj.value,
         xpath=obj.path)
     time.sleep(1)
     result = run_apple_script(cmd)
     if not result:
         return False
     pos_x = result.split(",")[0].strip()
     pos_y = result.split(",")[-1].split("\n")[0].strip()
     return pos_x, pos_y
示例#8
0
    def get_elements_in_view(self):
        """Returns a list of detected elements within the application current view

        :return: List of objects [{"type": 'the element role, "value": 'value or title', "path": 'position path'}]
        """
        logger.debug('Getting all elements in the view of "{}"'.format(
            self.get_application_process_name()))
        window_objects_dict_list = []

        # get all elements paths
        get_elements_apple_script = \
            'tell application "{sys_app}" to tell front window of application process "{app_name}" to return entire ' \
            'contents'.format(sys_app=self.system_level_application_name, app_name=self.get_application_process_name())
        result = run_apple_script(get_elements_apple_script)
        if not result:
            logger.error('Failed to get elements when running {}'.format(
                get_elements_apple_script))
            return
        application_process_name = re.findall('application process (.+?),',
                                              result)[0]
        elements_list = re.findall(
            '(.+? application process {}), '.format(application_process_name),
            result)
        paths_list = [item[item.index('of'):] for item in elements_list]
        if not paths_list:
            logger.error('Failed to get elements\' paths')
            return
        application_process_name = re.findall('application process (.+)',
                                              paths_list[0])[0]
        for index, path in enumerate(
                paths_list):  # wrap the main application process name with ""
            paths_list[index] = path.replace(
                application_process_name,
                '"{}"'.format(application_process_name))

        # get all elements names and classes
        get_elements_details_apple_script = \
            'set final to {{}}\n tell application "{sys_app}" \n tell front window of application process ' \
            '"{app_name}" \n repeat with ui_element in entire contents as list \n set current_ui to name of ' \
            'ui_element as string & ";" & class of ui_element as string & "$"\n set final to final & current_ui \n ' \
            'end repeat \n return final \n end tell \n end tell'.format(sys_app=self.system_level_application_name,
                                                                        app_name=self.get_application_process_name())
        result = run_apple_script(get_elements_details_apple_script)
        if not result:
            logger.error('Failed to get elements when running {}'.format(
                get_elements_details_apple_script))
            return
        elements_details_list = re.findall(r'(.+?)\$, ', result)
        elements_details_dict_list = [{
            'value': item.split(';')[0].strip(),
            'class': item.split(';')[1]
        } for item in elements_details_list]
        if not elements_details_dict_list:
            logger.error('Failed to get elements\' details')
            return
        if len(paths_list) != len(elements_details_dict_list):
            logger.error(
                'There\'s a Mismatch between the number of elemet\'s paths ({num_p}) and the number of '
                'elements details ({num_d})'.format(
                    num_p=len(paths_list),
                    num_d=len(elements_details_dict_list)))
            return

        # initiate an AppElement instance with the element's class, value and path
        for index, element_details in enumerate(elements_details_dict_list):
            element_class = element_details['class']
            try:
                element_value = str(element_details['value'])
            except UnicodeEncodeError:
                element_value = str(element_details['value'].encode('utf8'))
            element_value = element_value if element_value != 'missing value' else ''

            element_path = paths_list[index]
            #  wrap the parent window with "" if it exists and if it's not an integer
            reg_obj = re.findall('of window (.+?) of', element_path)
            parent_window = reg_obj[0] if reg_obj else ''
            if parent_window and not parent_window.isdigit():
                element_path = element_path.replace(
                    parent_window, '"{}"'.format(parent_window))

            window_objects_dict_list.append(
                AppElement(element_type=element_class,
                           element_value=element_value,
                           element_path=element_path))
        self.elements_in_current_view = window_objects_dict_list
        return self.elements_in_current_view