from pathlib import Path import re import sys import allure import pytest from playwright.sync_api import TimeoutError as PlaywrightTimeoutError from playwright.sync_api import expect PROJECT_ROOT = Path(__file__).resolve().parents[1] if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) from config.settings import settings from tests.test_rewards_shopping_cart_login_logout import ( _accept_cookie_if_present, _first_visible, _login_as_configured_user, ) from utils.logger import get_logger logger = get_logger(__name__) MY_ORDER_LINK_SELECTORS = [ 'a[href*="order" i]', 'a:has-text("My Order")', 'a:has-text("My Orders")', 'button:has-text("My Order")', 'button:has-text("My Orders")', 'div.cursor-pointer:has-text("My Order")', 'div.cursor-pointer:has-text("My Orders")', 'li:has-text("My Order")', 'li:has-text("My Orders")', 'text=My Order', 'text=My Orders', ] ORDER_DETAIL_LINK_SELECTORS = [ 'a[href*="order" i]', 'button:has-text("Detail")', 'button:has-text("Details")', 'button:has-text("View")', 'button:has-text("View Detail")', 'button:has-text("View Details")', ] def _click_first_visible_by_selectors(page, selectors, timeout=3_000): for selector in selectors: locator = page.locator(selector) try: if locator.count() == 0: continue candidate = _first_visible(locator) expect(candidate).to_be_visible(timeout=timeout) candidate.click() return selector except (AssertionError, PlaywrightTimeoutError): continue raise AssertionError(f"未找到可点击的可见元素: {selectors}") def _wait_login_completed(page): logger.info("等待登录完成并展示用户菜单入口") page.wait_for_function( """ () => { const visibleText = Array.from(document.querySelectorAll('a,button,div,li,span')) .filter(element => !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length)) .map(element => element.innerText || element.textContent || '') .join(' '); return /My Order|Logout|Create/i.test(visibleText) && !/^\\s*Login\\s*$/.test(visibleText); } """, timeout=settings.default_timeout, ) def _open_my_order_from_home(page): logger.info("从首页查找 My Order 入口") try: selector = _click_first_visible_by_selectors(page, MY_ORDER_LINK_SELECTORS) logger.info("已通过首页可见入口进入 My Order: %s", selector) return except AssertionError: logger.info("首页未直接展示 My Order,尝试点击用户侧边栏入口后继续查找") aside_buttons = page.locator("aside button") expect(aside_buttons.first).to_be_visible(timeout=settings.default_timeout) aside_buttons.first.click() page.wait_for_timeout(1_000) selector = _click_first_visible_by_selectors(page, MY_ORDER_LINK_SELECTORS, timeout=settings.default_timeout) logger.info("已通过用户菜单进入 My Order: %s", selector) def _open_first_order_detail(page): logger.info("等待进入订单列表页") expect(page).to_have_url(re.compile(r".*order.*", re.I), timeout=settings.default_timeout) expect(page.get_by_text(re.compile(r"my order|orders?|order", re.I)).first).to_be_visible( timeout=settings.default_timeout ) logger.info("点击第一笔订单详情入口") before_url = page.url selector = _click_first_visible_by_selectors(page, ORDER_DETAIL_LINK_SELECTORS, timeout=settings.default_timeout) logger.info("已点击订单详情入口: %s", selector) try: page.wait_for_url(lambda url: url != before_url, timeout=settings.default_timeout) except PlaywrightTimeoutError: logger.info("点击第一笔订单后 URL 未变化,继续校验当前页面是否展示详情内容") expect(page.locator("body")).to_be_visible(timeout=settings.default_timeout) expect(page.get_by_text(re.compile(r"order|detail|status|total|payment|shipping", re.I)).first).to_be_visible( timeout=settings.default_timeout ) @allure.feature("我的订单") @allure.story("订单详情") @allure.title("登录用户从首页进入 My Order 并查看第一笔订单详情") def test_home_my_order_first_order_detail_after_login(page, ensure_logged_in_user): logger.info("登录用户从首页进入 My Order 并查看第一笔订单详情") logger.info("打开链接地址: %s", settings.base_url) page.goto(settings.base_url, wait_until="domcontentloaded") ensure_logged_in_user() _wait_login_completed(page) _open_my_order_from_home(page) _open_first_order_detail(page) if __name__ == "__main__": raise SystemExit(pytest.main([str(Path(__file__))]))