Files
PlexPlaylistSync/tests/conftest_ui.py
T

162 lines
4.3 KiB
Python

"""
Pytest fixtures for UI testing
"""
import os
import subprocess
import time
from pathlib import Path
import pytest
from playwright.sync_api import Browser, Page
# 测试服务器配置
TEST_SERVER_HOST = os.getenv("TEST_SERVER_HOST", "localhost")
TEST_SERVER_PORT = int(os.getenv("TEST_SERVER_PORT", "8000"))
BASE_URL = f"http://{TEST_SERVER_HOST}:{TEST_SERVER_PORT}"
@pytest.fixture(scope="session")
def test_server():
"""
启动测试服务器(如果未运行)
如果服务器已经在运行,直接返回 URL。
否则,启动一个测试服务器进程。
"""
# 检查服务器是否已经在运行
try:
import requests
response = requests.get(BASE_URL, timeout=2)
if response.status_code < 500:
print(f"✓ 服务器已在运行: {BASE_URL}")
yield BASE_URL
return
except:
pass
# 启动服务器
print(f"启动测试服务器: {BASE_URL}")
project_root = Path(__file__).parent.parent
process = subprocess.Popen(
[
"uvicorn",
"app.main:app",
"--host", TEST_SERVER_HOST,
"--port", str(TEST_SERVER_PORT),
],
cwd=project_root,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
# 等待服务器启动
max_retries = 30
for i in range(max_retries):
try:
import requests
response = requests.get(BASE_URL, timeout=2)
if response.status_code < 500:
print(f"✓ 服务器启动成功 (尝试 {i+1}/{max_retries})")
break
except:
pass
time.sleep(1)
else:
process.kill()
raise RuntimeError(f"无法启动测试服务器: {BASE_URL}")
yield BASE_URL
# 清理
print("停止测试服务器")
process.terminate()
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
process.kill()
@pytest.fixture
def browser_context_args(browser_context_args):
"""配置浏览器上下文"""
return {
**browser_context_args,
"viewport": {"width": 1920, "height": 1080},
"locale": "zh-CN",
}
@pytest.fixture
def page(page: Page, test_server):
"""
配置页面并导航到首页
自动导航到测试服务器的首页,并等待页面加载完成。
"""
page.goto(test_server)
page.wait_for_load_state("networkidle")
# 设置默认超时
page.set_default_timeout(10000) # 10 秒
yield page
# 测试失败时截图
if page.context.browser.is_connected():
try:
screenshots_dir = Path(__file__).parent / "screenshots"
screenshots_dir.mkdir(exist_ok=True)
test_name = os.environ.get("PYTEST_CURRENT_TEST", "unknown").split(":")[-1].split(" ")[0]
screenshot_path = screenshots_dir / f"{test_name}.png"
page.screenshot(path=str(screenshot_path))
print(f"截图保存至: {screenshot_path}")
except Exception as e:
print(f"截图失败: {e}")
@pytest.fixture
def clean_rules(page: Page):
"""
清除所有规则的 fixture
在测试前清除所有现有的正则规则,确保测试从干净状态开始。
"""
# 清除所有规则
while page.locator(".rule-row").count() > 0:
try:
remove_btn = page.locator(".rule-row button[title='删除此规则']").first
remove_btn.click()
page.wait_for_timeout(50)
except:
break # 如果没有更多规则可删除
yield
# 测试后不清理,让下一个测试自己清理
# 这样可以在浏览器中查看测试结果
@pytest.fixture
def sample_rules():
"""提供示例规则数据"""
return [
{"pattern": r"/old/path/", "replacement": r"/new/path/"},
{"pattern": r"C:\\Music", "replacement": r"D:\\Audio"},
{"pattern": r"\\\\nas\\share", "replacement": r"Z:"},
]
@pytest.fixture
def nas_conversion_rules():
"""提供 NAS 路径转换规则"""
return [
{"pattern": r"\\\\koha9-nas\\koha9-nas\\Music", "replacement": r"N:\\Music"},
{"pattern": r"/music/cache/", "replacement": r"/data/music/"},
{"pattern": r"\\", "replacement": r"/"},
]