Files
smart-management-auto-test/Joyhub_ui_auto_test/tests/test_navigation_pages.py
zhouqi a94eb5dbbe feat: 新增JoyHub UI自动化测试目录
1. 新增 Joyhub_ui_auto_test/ 目录:
   - tests/ - 测试用例目录
   - pages/ - 页面元素定位
   - config/ - 配置文件
   - utils/ - 工具类
   - test_data/ - 测试数据
   - reports/ - 测试报告
   - webapp-testing/ - WebApp测试相关

2. 配置文件:
   - pytest.ini - pytest配置
   - requirements.txt - 依赖列表
   - README.md - 项目说明
2026-05-13 16:01:25 +08:00

173 lines
7.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pathlib import Path
import random
import re
import sys
import pytest
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 utils.logger import get_logger
logger = get_logger(__name__)
def test_header_download_app_navigation_then_home_return(page, ensure_guest_user):
logger.info("使用 pytest-playwright 统一无头浏览器配置")
logger.info("打开链接地址: %s", settings.base_url)
page.goto(settings.base_url, wait_until="domcontentloaded")
ensure_guest_user()
logger.info("点击顶部 /app 导航链接")
page.locator('header a[href="/app"]').first.click()
logger.info("校验跳转到 /app 页面")
expect(page).to_have_url(re.compile(r".*/app/?$"), timeout=settings.default_timeout)
expect(page.locator("body")).to_be_visible(timeout=settings.default_timeout)
logger.info("点击顶部首页链接返回首页")
page.locator('header a[href="/"]').first.click()
logger.info("校验返回首页成功")
expect(page).to_have_url(re.compile(r".*/?$"), timeout=settings.default_timeout)
expect(page.locator('button').first).to_be_visible(timeout=settings.default_timeout)
def test_footer_navigation_to_partnerships_and_faq(page, ensure_guest_user):
logger.info("使用 pytest-playwright 统一无头浏览器配置")
logger.info("打开链接地址: %s", settings.base_url)
page.goto(settings.base_url, wait_until="domcontentloaded")
ensure_guest_user()
logger.info("校验底部 Partnerships 和 FAQs 链接存在")
expect(page.locator('footer a[href="/partnerships"]')).to_be_attached(timeout=settings.default_timeout)
expect(page.locator('footer a[href="/faq"]')).to_be_attached(timeout=settings.default_timeout)
logger.info("打开 Partnerships 页面")
page.goto("/partnerships", wait_until="domcontentloaded")
logger.info("校验跳转到 Partnerships 页面")
expect(page).to_have_url(re.compile(r".*/partnerships/?$"), timeout=settings.default_timeout)
expect(page.locator("body")).to_be_visible(timeout=settings.default_timeout)
logger.info("打开 FAQ 页面")
page.goto("/faq", wait_until="domcontentloaded")
logger.info("校验跳转到 FAQ 页面")
expect(page).to_have_url(re.compile(r".*/faq/?$"), timeout=settings.default_timeout)
expect(page.locator("body")).to_be_visible(timeout=settings.default_timeout)
def test_about_us_blog_random_category_article_browse_success(page, ensure_guest_user, attach_page_screenshot):
logger.info("打开首页并进入 About Us 下的 Blog 页面")
page.goto(settings.base_url, wait_until="domcontentloaded")
ensure_guest_user()
page.wait_for_timeout(2_000)
about_us_menu = page.get_by_text("About Us", exact=True).first
expect(about_us_menu).to_be_visible(timeout=settings.default_timeout)
about_us_menu.click()
blog_link = page.locator('a[href="/blog-detail"]', has_text="Blog").first
expect(blog_link).to_be_visible(timeout=settings.default_timeout)
blog_link.click()
logger.info("校验 Blog 页面加载成功")
expect(page).to_have_url(re.compile(r".*/blog-detail/?$"), timeout=settings.default_timeout)
expect(page.locator("body")).to_contain_text("SEXUAL WELLNESS HUB", timeout=settings.default_timeout)
category_buttons = page.locator("button").filter(has_not_text=re.compile(r"^\\d+$|Acce?pet", re.I))
expect(category_buttons.first).to_be_visible(timeout=settings.default_timeout)
category_count = category_buttons.count()
category_indexes = list(range(category_count))
random.shuffle(category_indexes)
selected_category = None
article_links = page.locator('a[href^="/blog-detail/"]')
for category_index in category_indexes:
category_button = category_buttons.nth(category_index)
selected_category = category_button.inner_text(timeout=settings.default_timeout).strip()
logger.info("随机选择 Blog 分类: %s", selected_category)
category_button.click()
page.wait_for_load_state("domcontentloaded")
try:
expect(article_links.first).to_be_visible(timeout=5_000)
if article_links.count() > 0:
break
except AssertionError:
logger.info("分类 %s 下暂无可浏览 Blog继续随机尝试其他分类", selected_category)
else:
raise AssertionError("所有 Blog 分类下均未找到可浏览文章")
article_count = article_links.count()
article_index = random.randrange(article_count)
article_link = article_links.nth(article_index)
article_title = article_link.inner_text(timeout=settings.default_timeout).strip()
logger.info("随机浏览 Blog 文章: %s", article_title)
article_href = article_link.get_attribute("href")
assert article_href is not None
article_link.scroll_into_view_if_needed(timeout=settings.default_timeout)
article_link.click()
logger.info("校验 Blog 详情页加载成功并截图")
expect(page).to_have_url(re.compile(r".*/blog-detail/.+"), timeout=settings.default_timeout)
expect(page.locator("body")).to_be_visible(timeout=settings.default_timeout)
if article_title:
expect(page.locator("body")).to_contain_text(article_title, timeout=settings.default_timeout)
attach_page_screenshot(f"Blog浏览成功_{selected_category}_{article_title or article_href}")
def test_footer_social_media_links_open_then_return_home(page, ensure_guest_user):
social_links = [
("X", 'a[href="https://x.com/JoyhubOfficial"]', re.compile(r"https://(x|twitter)\.com/.*", re.I)),
(
"Instagram",
'a[href="https://www.instagram.com/joyhub.official/#"]',
re.compile(r"https://www\.instagram\.com/.*", re.I),
),
(
"Reddit",
'a[href="https://www.reddit.com/r/JoyhubRemote/"]',
re.compile(r"https://www\.reddit\.com/.*", re.I),
),
(
"Discord",
'a[href="https://discord.com/invite/vZFQbTRZqe"]',
re.compile(r"https://discord\.com/.*", re.I),
),
]
logger.info("打开链接地址: %s", settings.base_url)
page.goto(settings.base_url, wait_until="domcontentloaded")
ensure_guest_user()
for name, selector, expected_url in social_links:
logger.info("滚动到首页底部,点击 %s 社交媒体按钮", name)
page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
link = page.locator(selector).first
expect(link).to_be_attached(timeout=settings.default_timeout)
link.scroll_into_view_if_needed(timeout=settings.default_timeout)
social_href = link.get_attribute("href")
assert social_href is not None
logger.info("校验 %s 社交媒体页面跳转成功", name)
page.goto(social_href, wait_until="domcontentloaded")
expect(page).to_have_url(expected_url, timeout=settings.default_timeout)
logger.info("%s 页面返回 JoyHub 首页", name)
page.goto(settings.base_url, wait_until="domcontentloaded")
expect(page).to_have_url(re.compile(r".*/?$"), timeout=settings.default_timeout)
expect(page.locator('a[href="https://x.com/JoyhubOfficial"]')).to_be_attached(timeout=settings.default_timeout)
if __name__ == "__main__":
raise SystemExit(pytest.main([str(Path(__file__))]))