137 lines
4.8 KiB
Python
137 lines
4.8 KiB
Python
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__))]))
|