"""Web 登录功能测试用例。 覆盖: - (skip_login: true) 验证预登录态有效,不经过 UI 登录页 - (skip_login: false) 完整 UI 登录流程 + 表单校验 标记: pytest -m web # 仅执行 Web 用例 pytest -m p0 # 仅执行 P0 冒烟 pytest -m smoke # 仅执行冒烟 """ import pytest from playwright.sync_api import Page pytestmark = [pytest.mark.web] # ═══════════════════════════════════════════════════════════════════ # P0 — 冒烟测试(依赖预登录态,不触发 UI 登录) # ═══════════════════════════════════════════════════════════════════ class TestLoginSmoke: """验证预登录态有效 + 后台可正常访问。""" @pytest.mark.p0 @pytest.mark.smoke def test_admin_access_with_saved_auth(self, page: Page, web_config, ensure_login): """验证加载预登录态后可直接访问管理后台,无需重新登录。""" ensure_login("super_admin") page.goto(web_config["base_url"]) # 已登录状态下不应重定向到登录页 assert "/login" not in page.url, ( f"预登录态失效!仍然重定向到登录页。请运行: python tests/web/save_auth.py" ) @pytest.mark.p0 @pytest.mark.smoke def test_team_leader_access_with_saved_auth(self, page: Page, web_config, ensure_login): """验证车队长预登录态有效。""" ensure_login("team_leader") page.goto(web_config["base_url"]) assert "/login" not in page.url @pytest.mark.p0 @pytest.mark.smoke def test_dashboard_loads(self, page: Page, web_config, ensure_login): """验证登录后首页能正常加载。""" ensure_login("super_admin") page.goto(web_config["base_url"]) # 页面标题应包含"运八"或类似标识 assert page.title(), "首页应显示页面标题" # ═══════════════════════════════════════════════════════════════════ # P1 — 登录页交互(仅在 skip_login: false 时才有意义) # ═══════════════════════════════════════════════════════════════════ class TestLoginPageDirect: """直接访问登录页相关用例(不依赖账号)。""" @pytest.mark.p1 def test_login_page_accessible(self, page: Page, web_config): """验证登录页可直接访问并正常渲染。""" page.goto(f"{web_config['base_url']}/login") # 登录页应存在用户名输入框 assert page.getByPlaceholder("请输入用户名").is_visible() @pytest.mark.p1 def test_login_page_elements(self, page: Page, web_config): """验证登录页所有关键元素存在。""" page.goto(f"{web_config['base_url']}/login") assert page.getByPlaceholder("请输入用户名").is_visible() assert page.getByPlaceholder("请输入密码").is_visible() assert page.getByRole("button", name="登录").is_visible() @pytest.mark.p1 def test_double_login_session_redirect(self, page: Page, web_config, ensure_login): """验证已登录用户访问 /login 页自动重定向。""" ensure_login("super_admin") page.goto(web_config["base_url"]) assert "/login" not in page.url # 已登录状态再次访问 /login page.goto(f"{web_config['base_url']}/login") # 应被重定向到后台 assert "/login" not in page.url, ( f"已登录用户访问 /login 应被重定向,当前: {page.url}" ) # ═══════════════════════════════════════════════════════════════════ # P2 — UI 登录流程(仅 skip_login: false 时执行,有验证码时预期跳过) # ═══════════════════════════════════════════════════════════════════ @pytest.mark.p2 @pytest.mark.skip_login_required # 自定义 marker:仅在 skip_login: false 时生效 class TestLoginUI: """完整 UI 登录(需要 skip_login: false)。""" def test_full_ui_login_super_admin(self, page: Page, web_config, ensure_login): """通过 UI 完成完整登录(需要手动关闭 skip_login)。""" ensure_login("super_admin") page.goto(web_config["base_url"]) assert "/login" not in page.url