def create_workday(self, tile_name, val, num=0): """ 添加特殊工作日 :param tile_name: 动态传入定位表达式的标题名称 :param val: 特殊工作日名称 :param num: 设置动态数值,保证时间选择不同 """ # 定位 - 未定义工作日 - 按钮 SET_WORKDAY = (By.XPATH, '//span[contains(text(), "未定义工作日")]') if not self.driver.find_element(*SET_WORKDAY).is_displayed(): # TODO 判断元素在页面是否可见 ele.is_displayed(),默认可见 # 元素滚动到页面可见区域 BasePage(self.driver).scroll_visibility_region(loc=SET_WORKDAY) # 点击 - 未定义工作日 - 按钮 BasePage(self.driver).click_ele(SET_WORKDAY) # 调用封装方法 - 添加特殊工作日 self.dialog_info_com(tile_name, val) # 点击 - 设定日期 - 按钮 SET_TIME = ( By.XPATH, '//header[contains(text(), "特殊工作日定义")]/following-sibling::div//span[contains(text(), "设定日期")]' ) BasePage(self.driver).click_ele(SET_TIME) # 调用封装方法 - 选择特殊工作日的时间区间 self.check_time(num)
def click_nav_item(self, menu_text, sub_menu_text=None): """ 封装导航栏组件:传入的参数是一级还是二级导航 :param menu_text: 菜单文本<导航文本的唯一性> :param sub_menu_text: 子菜单文本 :return: """ # 当推送消息过多,系统会弹出消息提示,但是会挡住nav导航条,所以需要在定位元素之前进行判断和关闭 try: INFO_TEXT = (By.XPATH, '//div[@role="alert"]//p') # WebDriverWait(self.driver, 5).until(EC.visibility_of_element_located(INFO_TEXT)) WebDriverWait(self.driver, 20).until(EC.presence_of_element_located(INFO_TEXT)) except: # 此处设置日志的等级为debug,仅仅是为了自己能在控制台中查看,不算抛出异常 self.log.debug("-------------无消息弹框出现---------------") else: AlertInfoPage(self.driver).close_alert() if menu_text == "工具": MENU_TEXT = (By.XPATH, f'//div[text()="{menu_text}"]') SUB_MENU_TEXT = (By.XPATH, f'//li[text()="{sub_menu_text}"]') else: MENU_TEXT = (By.XPATH, f'//em[text()="{menu_text}"]') SUB_MENU_TEXT = (By.XPATH, f'//em[text()="{sub_menu_text}"]') if sub_menu_text is not None: # 通过移动到一级目录然后点击二级目录 BasePage(self.driver).mouse_move_ele(MENU_TEXT) BasePage(self.driver).mouse_move_ele_and_click( MENU_TEXT, SUB_MENU_TEXT) else: # 选择指定的一级目录 BasePage(self.driver).click_ele(MENU_TEXT)
def draw_park_region(self, default="region"): if default == "region": # 定位点击绘制区域的按钮 REGION_BTN = (By.XPATH, '//i/parent::div[contains(text(), "点击绘制区域 ")]') elif default == "line": REGION_BTN = (By.XPATH, '//i/parent::div[contains(text(), "点击绘制告警线")]') BasePage(self.driver).click_ele(REGION_BTN) # 滚动到视频违停区域 VIEW_REGION = (By.XPATH, '//div[@class="addTaskPC-video"]') BasePage(self.driver).scroll_visibility_region(loc=VIEW_REGION) time.sleep(2) # 绘制区域 PARK_REGION = (By.CSS_SELECTOR, '.draw-line') ele = BasePage(self.driver).get_ele_locator(PARK_REGION) if default == "region": # 绘制告警区域的传参形式 draw_param = [(-100, -100), (100, -100), (100, 100), (-100, 100), (-100, -100)] elif default == "line": # 绘制告警线的传参形式 draw_param = [(-100, -100), (100, 100)] # 循环进行线条的绘制 for point in draw_param: self.draw_line(point[0], point[1], ele)
def operations_table_list(self, name, flag): """ 定位列表项的相关操作,有:查看、编辑、删除 """ # 定位查看icon VIEW_ICON = ( By.XPATH, f'//table[@class="el-table__body"]//div[@class="cell" and text() = "{name}"]/parent::td/following-sibling::td[contains(@class, "tables-operate")]//i[contains(@class, "icon-view")]' ) # 定位编辑icon EDIT_ICON = ( By.XPATH, f'//table[@class="el-table__body"]//div[@class="cell" and text() = "{name}"]/parent::td/following-sibling::td[contains(@class, "tables-operate")]//i[contains(@class, "icon-edit")]' ) # 定位删除icon DELETE_ICON = ( By.XPATH, f'//table[@class="el-table__body"]//div[@class="cell" and text() = "{name}"]/parent::td/following-sibling::td[contains(@class, "tables-operate")]//i[contains(@class, "icon-delete")]' ) # 点击查看、 编辑、删除icon if flag == "view": BasePage(self.driver).click_ele(VIEW_ICON) elif flag == "edit": BasePage(self.driver).click_ele(EDIT_ICON) elif flag == "delete": BasePage(self.driver).click_ele(DELETE_ICON) # 进行弹框删除操作 DialogPage(self.driver).operation_dialog_btn(btn_text="删除")
def is_delete_or_cancel(self, module_val, is_delete=True): """ 弹框删除操作 :param module_val: 不同模块共用,由于元素定位不一样,需要动态传入删除操作的模块 :param is_delete: :return: """ # 如果是用户模块的删除操作 if module_val == "user" or module_val == "device": # 定位删除按钮 DELETE_BTN = (By.XPATH, '//span[contains(text(),"删除")]/parent::div/following-sibling::div[@class="el-dialog__footer"]//span[contains(text(),"删除")]') # 定位取消按钮 CANCEL_BTN = (By.XPATH, '//span[contains(text(),"删除")]/parent::div/following-sibling::div[@class="el-dialog__footer"]//span[contains(text(),"取消")]') # 如果是地图模块的删除操作 elif module_val == "map": DELETE_BTN = (By.XPATH, '//span[contains(text(),"删除")]/ancestor::div[@class="el-message-box"]//button//span[contains(text(), "删除")]') CANCEL_BTN = (By.XPATH, '//span[contains(text(),"删除")]/ancestor::div[@class="el-message-box"]//button//span[contains(text(), "取消")]') elif module_val == "timezone": DELETE_BTN = (By.XPATH, '//button//span[contains(text(), "删除")]') CANCLE_BTN = (By.XPATH, '//button//span[contains(text(), "取消")]') if is_delete: # 点击删除按钮 BasePage(self.driver).click_ele(DELETE_BTN) else: # 点击取消按钮 BasePage(self.driver).click_ele(CANCEL_BTN)
def delete_or_rename_timezone_name(self, timezone_name, flag="删除"): """ 删除时间条件 """ # 定位到当前时间条件名称 SELECT_TIMEZONE = ( By.XPATH, f'//div[@role="tablist"]//button/span[contains(text(), "{timezone_name}")]' ) BasePage(self.driver).mouse_move_ele(SELECT_TIMEZONE) if flag == "重命名": # TODO ELE_LOC = ( By.XPATH, '//div[@role="tooltip" and contains(@style, "position")]//span[contains(text(), "重命名")]' ) BasePage(self.driver).mouse_move_ele_and_click( SELECT_TIMEZONE, ELE_LOC) # 执行重命名操作 self.dialog_info_com("重命名时间条件", "UPDATE" + timezone_name) elif flag == "删除": # 定位到 "删除" 元素 ELE_LOC = ( By.XPATH, '//div[@role="tooltip" and contains(@style, "position")]//span[contains(text(), "删除")]' ) time.sleep(2) BasePage(self.driver).mouse_move_ele_and_click( SELECT_TIMEZONE, ELE_LOC) # 执行删除操作 DialogPage(self.driver).is_delete_or_cancel(module_val="timezone")
def check_all(self): ALL_SELECT = ( By.XPATH, '//div[@class="el-table__header-wrapper"]//div[text()="任务名称"]/parent::th/preceding-sibling::th//span[@class="el-checkbox__input"]' ) BasePage(self.driver).wait_for_ele_to_be_visible(ALL_SELECT) BasePage(self.driver).click_ele(ALL_SELECT)
def create_holidays(self, tile_name, holidays, num=0): """ 添加假期 :param tile_name: 动态传入定位表达式的标题名称 :param holidays: 假期名称 :param num: 设置动态数值,保证时间选择不同 """ # 定位 - 未定义假期 - 按钮 SET_HOLIDAY = (By.XPATH, '//span[contains(text(), "未定义假期")]') # 先等待元素存在,然后对目标元素是否可见进行判断 BasePage(self.driver).wait_for_ele_to_be_presence(SET_HOLIDAY) # TODO 判断当前元素在页面中是否可见。ele.is_displayed() if not self.driver.find_element(*SET_HOLIDAY).is_displayed(): # 元素滚动到页面可见区域 BasePage(self.driver).scroll_visibility_region(loc=SET_HOLIDAY) # 点击 - 未定义假期 - 按钮 BasePage(self.driver).click_ele(SET_HOLIDAY) # 调用封装方法 - 添加假期 self.dialog_info_com(tile_name, holidays) # 点击 - 设定日期 - 按钮 SET_TIME = ( By.XPATH, '//header[contains(text(), "假期定义")]/following-sibling::div//span[contains(text(), "设定日期")]' ) BasePage(self.driver).click_ele(SET_TIME) # 调用封装方法 - 选择假期的时间区间 self.check_time(num)
def comm_search_result_by_name(self, name): # 点击出现下拉选择搜索框 CLICK_BTN = ( By.XPATH, '//div[@class="condition-box"]//div[contains(@class, "tree-input")]//span[contains(text(), "设备")]/following-sibling::div' ) BasePage(self.driver).click_ele(CLICK_BTN) # 强制等待3秒,等下拉列表全部加载完成,再进行搜索查询 # TODO 判断设备列表是否成功加载出来 try: CONTENT_WRAP = ( By.XPATH, '//ul[contains(@class, "el-dropdown-menu") and not(contains(@style, "display: none;"))]//div[@class="el-tree"]//div' ) WebDriverWait(self.driver, 30).until( EC.visibility_of_element_located(CONTENT_WRAP)) except: time.sleep(3) time.sleep(3) # 通过设备名device_name,查找设备 SELECT_GROUP = ( By.XPATH, '//ul[contains(@class, "el-dropdown-menu") and not(contains(@style, "display: none;"))]//div[contains(@class, "el-input")]//input' ) BasePage(self.driver).update_input_text(SELECT_GROUP, name) # 通过 name, 定位到查询结果 RESULT = ( By.XPATH, f'//ul[contains(@class, "el-dropdown-menu") and not(contains(@style, "display: none;"))]//div[@class="el-tree-node__content"]//span[text()="{name}"]/preceding-sibling::span/following-sibling::label' ) # 点击查询到的name BasePage(self.driver).click_ele(RESULT)
def input_park_time(self, time_minute=1): PARK_TIME = ( By.XPATH, '//label[contains(text(), "违停时限")]/following-sibling::div//input') # 先清空输入框内的数值 BasePage(self.driver).clear_input_default_val(PARK_TIME) # 再输入目标分钟数 BasePage(self.driver).update_input_text(PARK_TIME, time_minute)
def search_dep_by_name(self, group_name): # 定位搜索文本框 SEARCH_INPUT = (By.XPATH, '//aside[@class="el-aside"]//div[contains(@class,"el-input--suffix")]/input') BasePage(self.driver).update_input_text(SEARCH_INPUT, group_name) # 点击搜索 SEARCH_BTN = (By.XPATH, '//aside[@class="el-aside"]//div[contains(@class,"el-input--suffix")]/span') BasePage(self.driver).click_ele(SEARCH_BTN)
def evaluate_face_image_quality(self, path): """ 质量分数检测 """ # 上传人脸图片 IMAGE_UPLOAD_INPUT = (By.CSS_SELECTOR, 'input[type="file"]') # 点击检测按钮 CHECK_CONTENT_DETECTION_BUTTON = ( By.CSS_SELECTOR, '.app-tools-content-detection-detectbtn') BasePage(self.driver).upload_file(IMAGE_UPLOAD_INPUT, path) BasePage(self.driver).click_ele(CHECK_CONTENT_DETECTION_BUTTON)
def detect_facial_attribute(self, path): """ 人脸属性检测 """ # 图片上传按钮 IMAGE_UPLOAD_INPUT = (By.CSS_SELECTOR, 'input[type="file"]') # 点击检测 CHECK_CONTENT_FACE_BUTTON = (By.CSS_SELECTOR, '.app-tools-content-face-detectbtn') BasePage(self.driver).upload_file(IMAGE_UPLOAD_INPUT, path) BasePage(self.driver).click_ele(CHECK_CONTENT_FACE_BUTTON)
def select_task_type(self, task_type): # 此处,采用的是先点击左侧对应的菜单,所以次数不需要下拉选择 TASK_DEVICE = ( By.XPATH, '//label[contains(text(), "任务类型")]/following-sibling::div//input') BasePage(self.driver).click_ele(TASK_DEVICE) # 定位任务类型 SELECT_TASK_DEV = (By.XPATH, f'//span[text()="{task_type}"]') # 移动到任务累心上并进行选择 BasePage(self.driver).mouse_move_ele_and_click(TASK_DEVICE, SELECT_TASK_DEV)
def comm_search_result_by_name(self, name): """ 下拉列表搜索 """ # 1、通过设备分组名device_group_name,查找设备 SELECT_GROUP = (By.XPATH, '//div[@role="tooltip" and contains(@style, "position")]//div[contains(@class, "el-input--small")]//input') BasePage(self.driver).update_input_text(SELECT_GROUP, name) # 2、通过设备分组名device_group_name, 定位到查询结果 RESULT = (By.XPATH, f'//span[@class="el-radio__label" and text() = "{name}"]') # 点击到查询的设备分组名 BasePage(self.driver).click_ele(RESULT)
def is_confirm_or_cancel(self, loc_by_til, is_confirm=True): if is_confirm: # 定位确认按钮 CONFIRM_BTN = (By.XPATH, f'//span[contains(text(),"{loc_by_til}")]/parent::div/following-sibling::div[@class="el-dialog__footer"]//span[contains(text(),"确定")]') BasePage(self.driver).click_ele(CONFIRM_BTN) else: # 定位取消按钮 CANCLE_BTN = (By.XPATH, f'//span[contains(text(),"{loc_by_til}")]/parent::div/following-sibling::div[@class="el-dialog__footer"]//span[contains(text(),"取消")]') # CANCLE_BTN = (By.XPATH, f'//div[@aria-label="{loc_by_til}"]/parent::div[not(@style="display: none;")]//span[@class="dialog-footer"]//span[text()="取消"]') BasePage(self.driver).click_ele(CANCLE_BTN)
def select_device_type(self, device_type): # 定位设备类型框 并点击 TYPE = (By.XPATH, '//label[contains(text(), "设备类型")]/following-sibling::div//input') # 通过传入的不同设备类型 - 去动态定位设备类型 SELECT_TYPE = (By.XPATH, f'//div[contains(@class,"el-popper") and contains(@style, "position")]//ul[contains(@class, "el-select-dropdown__list")]//span[contains(text(), "{device_type}")]') BasePage(self.driver).click_ele(TYPE) time.sleep(0.2) # 移动到type元素并选择目标元素 BasePage(self.driver).mouse_move_ele_and_click(TYPE, SELECT_TYPE)
def dialog_error_info(self, flag="task"): # 通过不同的flag定位不同的错误信息元素定位表达式,并返回错误信息 ERROR_INFO = (By.XPATH, '//div[@class="el-form-item__error"]') if flag == "task": # 如果是校验设备名的错误信息,下标为0 ele = BasePage(self.driver).get_ele_locator_by_index(ERROR_INFO, 0) elif flag == "device": ele = BasePage(self.driver).get_ele_locator_by_index(ERROR_INFO, 1) elif flag == "region": ele = BasePage(self.driver).get_ele_locator_by_index(ERROR_INFO, 2) elif flag == "direction": ele = BasePage(self.driver).get_ele_locator_by_index(ERROR_INFO, 3) return ele.text
def click_filter_or_reset_btn(self, default="filter"): if default == "filter": BTN = ( By.XPATH, '//div[@class="condition-box"]//div[@class="operate"]//span[contains(text(), "筛选")]' ) # 点击筛选 BasePage(self.driver).click_ele(BTN) else: BTN = ( By.XPATH, '//div[@class="condition-box"]//div[@class="operate"]//span[contains(text(), "重置")]' ) # 点击重置 BasePage(self.driver).click_ele(BTN)
def verify_view_task_detail(self): """ 验证查看任务详情是否是当前任务名的详情 """ TASK_NAME = ( By.XPATH, '//label[contains(text(), "任务名称")]/following-sibling::div') time.sleep(2) return BasePage(self.driver).get_text(TASK_NAME)
def assert_timezone_section(self): # 判断添加时间段是否成功 CHECK_CON_RESULT = ( By.XPATH, '//div[@class="el-tab-pane" and @style=""]//div[contains(@class, "el-row")]//span[contains(text(), ":")]' ) return BasePage(self.driver).get_text(CHECK_CON_RESULT)
def com_car_size(self, text_name, width=30, height=30): # 定位宽 SIZE_WIDTH = ( By.XPATH, f'//label[contains(text(), "{text_name}")]/following-sibling::div//label[text()="宽"]/following-sibling::div//input' ) # 定位高 SIZE_HEIGHT = ( By.XPATH, f'//label[contains(text(), "{text_name}")]/following-sibling::div//label[text()="高"]/following-sibling::div//input' ) # 先清空input框中的默认数值 BasePage(self.driver).clear_input_default_val(SIZE_WIDTH) BasePage(self.driver).clear_input_default_val(SIZE_HEIGHT) # 进行数值输入 BasePage(self.driver).update_input_text(SIZE_WIDTH, width) BasePage(self.driver).update_input_text(SIZE_HEIGHT, height)
def select_device_site(self, map_group_name="Default", is_confirm=True): """ 标准设备在地图中的点位 """ SITE = (By.XPATH, '//label[contains(text(), "地点")]/following-sibling::div//span') # 点击按钮 - 在弹框界面进行设备点位标注 BasePage(self.driver).click_ele(SITE) # 搜索地图设备分组,并点击搜索到的结果 SEARCH_GROUP = (By.XPATH, '//input[contains(@placeholder, "请输入平面图名称")]') BasePage(self.driver).update_input_text(SEARCH_GROUP, map_group_name) MAP_GROUP = (By.XPATH, f'//span[contains(text(), "{map_group_name}")]') BasePage(self.driver).click_ele(MAP_GROUP) # 定位 - 地图点位图标 MAP_POINT = (By.XPATH, '//a[contains(@title, "Draw a marker")]') BasePage(self.driver).click_ele(MAP_POINT) # 定位 - 地图容器 TARGET_ELE = (By.XPATH, '//div[@class="leaflet-control-container"]') BasePage(self.driver).mouse_move_to_ele_and_offset(x_offset=100, y_offset=100, loc=TARGET_ELE) if is_confirm: # 点击确定 CONFIRM_BTN = ( By.XPATH, '//div[contains(@class, "dialog-track")]//span[contains(text(), "确定")]') BasePage(self.driver).click_ele(CONFIRM_BTN) else: # 点击取消 CANCLE_BTN = ( By.XPATH, '//div[contains(@class, "dialog-track")]//span[contains(text(), "取消")]') BasePage(self.driver).click_ele(CANCLE_BTN)
def select_special_attr(self, attr_name: list): """ 特殊属性支持多选:入口,出口,第三方对接 """ # 定位特殊属性选择框 SPECIAL_ATTR = ( By.XPATH, '//label[contains(text(), "特殊属性")]/following-sibling::div//input') BasePage(self.driver).click_ele(SPECIAL_ATTR) if attr_name is not None: for single_attr in attr_name: # 通过指定特殊属性的名称,进行选择 SELECT_ATTR = (By.XPATH, f'//span[text()="{single_attr}"]') # 移动到特殊属性下拉列表上并进行选择 BasePage(self.driver).mouse_move_ele_and_click( SPECIAL_ATTR, SELECT_ATTR) else: BasePage(self.driver).click_ele(SPECIAL_ATTR)
def click_group_by_name(self, group_name="Default"): """ 点击树图分组 :param group_name: 分组名称 """ # 定位分组名 DEPARTMENT_NAME = (By.XPATH, f'//div[@title="{group_name}"]') BasePage(self.driver).click_ele(DEPARTMENT_NAME)
def update_input_park_time(self, task_name, is_confirm=True): # 点击编辑icon TableListPage(self.driver).operations_table_list(task_name, flag="edit") # 修改违停时限为2分钟 self.input_park_time(2) # 点击确认或取消按钮 if is_confirm: CONFIRM_BTN = ( By.XPATH, f'//div[@aria-label="编辑"]/parent::div[not(@style="display: none;")]//span[@class="dialog-footer"]//span[text()="确定"]' ) BasePage(self.driver).click_ele(CONFIRM_BTN) else: CONFIRM_BTN = ( By.XPATH, f'//div[@aria-label="编辑"]/parent::div[not(@style="display: none;")]//span[@class="dialog-footer"]//span[text()="取消"]' ) BasePage(self.driver).click_ele(CONFIRM_BTN)
def select_device_group(self, device_group_name="Defualt", is_confirm=True): """ 定位到设备分组 - 并为当前创建的设备选择设备组 """ GROUP = (By.XPATH, '//label[contains(text(), "分组")]/following-sibling::div') time.sleep(0.2) BasePage(self.driver).click_ele(GROUP) # 选择设备分组 self.comm_search_result_by_name(device_group_name) if is_confirm: # 点击确定 CONFIRM_BTN = ( By.XPATH, '//div[@role="tooltip" and contains(@style, "position")]//span[contains(text(), "确定")]') BasePage(self.driver).click_ele(CONFIRM_BTN) else: # 点击取消 CANCLE_BTN = ( By.XPATH, '//div[@role="tooltip" and contains(@style, "position")]//span[contains(text(), "取消"]') BasePage(self.driver).click_ele(CANCLE_BTN)
def select_device(self, device_name): DEVICE = ( By.XPATH, '//label[contains(text(), "设备")]/following-sibling::div//div[contains(@class, "el-popover__reference")]//input' ) BasePage(self.driver).click_ele(DEVICE) # 通过设备名搜索设备并选择 self.comm_search_result_by_name(device_name)
def click_menu_name_by_move_icon(self, group_name, menu_name): """ 滑动到icon进行menu菜单选择操作 :param group_name: 组名称 :param menu_name: 组右侧动态出现的菜单选择操作 """ # 定位分组右侧icon GROUP_ICON = (By.XPATH, f'//div[@title="{group_name}"]/parent::div/following-sibling::div[contains(text(), "︙")]') # 定位menu容器 MENU = (By.ID, 'menu') # 通过传入不同的 menu_name 滑动到不同的操作 MENU_NAME = (By.XPATH, f'//div[@id="menu"]//li[@class="menu" and contains(text(), "{menu_name}")]') time.sleep(1) # 滑动到icon元素上 BasePage(self.driver).mouse_move_ele(GROUP_ICON) # 滑动到menu元素上并点击操作名,如:创建同级 BasePage(self.driver).mouse_move_ele_and_click(MENU, MENU_NAME)
def verify_one_to_one_face(self, path1, path2): """ 1:1人脸验证 """ # 上传左侧图片 IMAGE_UPLOAD_INPUT_L = ( By.CSS_SELECTOR, '.app-tools-content-pics .imageselsect-container:first-child > input[type="file"]' ) # 上传右侧图片 IMAGE_UPLOAD_INPUT_R = ( By.CSS_SELECTOR, '.app-tools-content-pics .imageselsect-container:last-child > input[type="file"]' ) # 点击比对按钮 CHECK_CONTENT_FACE_BUTTON = (By.CLASS_NAME, "app-tools-content-pics-vsbtn") # input类型的file文件上传 BasePage(self.driver).upload_file(IMAGE_UPLOAD_INPUT_L, path1) BasePage(self.driver).upload_file(IMAGE_UPLOAD_INPUT_R, path2) BasePage(self.driver).click_ele(CHECK_CONTENT_FACE_BUTTON)