From a361ba705315a3e6e8c12ca99b8df19f3d4d3f12 Mon Sep 17 00:00:00 2001 From: xst Date: Wed, 22 Jul 2026 17:31:19 +0800 Subject: [PATCH] =?UTF-8?q?fix(login):=20use=20text=20selectors=20for=20bo?= =?UTF-8?q?ttom=20nav=20tabs=20=E9=A6=96=E9=A1=B5/=E8=B4=A7=E6=BA=90/?= =?UTF-8?q?=E6=88=91=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace coordinate tap with text-based UiSelector for reliability. Add back-press loop to ensure app is on main page before checking login. --- tests/app/_shared.py | 58 +++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/tests/app/_shared.py b/tests/app/_shared.py index 2adb763..ecfaa22 100644 --- a/tests/app/_shared.py +++ b/tests/app/_shared.py @@ -54,8 +54,10 @@ def make_ensure_logged_in( ): """创建一个 ensure_logged_in 闭包。 - 策略:坐标点击底部"我的"tab(第4个图标)→ 检查"登录/注册"文本。 - 无法通过 resourceId 或 text 定位底部导航时用坐标点击兜底。 + 策略: + 1. 反复点击返回键,直到底部导航栏(首页/货源/我的)全部可见 + 2. 点击"我的"tab,检查"登录/注册"文本是否存在 + 3. 不存在 → 已登录;存在 → 未登录 Args: section_config: App 端配置 @@ -71,18 +73,35 @@ def make_ensure_logged_in( skip_login = section_config.get("skip_login", True) wait = WebDriverWait(driver, timeout=timeout_s) - driver.implicitly_wait(3) + # ── 底部导航栏三个 tab 定位(使用 text 定位,更可靠)── + home_tab = (AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("首页")') + freight_tab = (AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("货源")') + mine_tab = (AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("我的")') - # 坐标点击底部"我的"tab(4 tab 均分宽度,第4个中心 x≈0.875*w, y≈h-50) - try: - w = driver.get_window_size()["width"] - h = driver.get_window_size()["height"] - driver.tap([(int(w * 0.875), h - 50)]) - driver.implicitly_wait(1) - except Exception as e: - raise RuntimeError(f"无法点击底部导航栏: {e}") + # ── 步骤1: 返回到一级页面 ── + # 不断点返回键,直到三个底部导航 tab 都可见 + max_back_presses = 20 + for _ in range(max_back_presses): + home_visible = _is_displayed(driver, home_tab) + freight_visible = _is_displayed(driver, freight_tab) + mine_visible = _is_displayed(driver, mine_tab) - # 判断登录态:检查"登录/注册"文本 + if home_visible and freight_visible and mine_visible: + break + + # 不在一级页面 → 点击返回 + try: + driver.back() + driver.implicitly_wait(1) + except Exception: + break + + # ── 步骤2: 点击"我的"tab ── + wait.until(EC.visibility_of_element_located(mine_tab)) + driver.find_element(*mine_tab).click() + driver.implicitly_wait(1) + + # ── 步骤3: 判断登录态 ── login_check = (AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("登录/注册")') try: el = driver.find_element(*login_check) @@ -99,11 +118,7 @@ def make_ensure_logged_in( except Exception: pass # 没找到"登录/注册" → 已登录 - # 回到首页 - home_tab = ( - AppiumBy.ANDROID_UIAUTOMATOR, - 'new UiSelector().resourceId("com.arpa.ynchenggangdriver:id/fixed_bottom_navigation_icon").instance(0)', - ) + # ── 步骤4: 回到首页 ── try: wait.until(EC.visibility_of_element_located(home_tab)) driver.find_element(*home_tab).click() @@ -113,6 +128,15 @@ def make_ensure_logged_in( return _ensure_logged_in +def _is_displayed(driver, locator) -> bool: + """检查元素是否可见(不抛异常)。""" + try: + el = driver.find_element(*locator) + return el.is_displayed() + except Exception: + return False + + def _perform_ui_login(driver, account: dict, wait) -> None: """执行 UI 自动登录(skip_login: false 时使用)。""" from appium.webdriver.common.appiumby import AppiumBy