""" 首页 E2E(INV-017 八入口固定 / INV-016 Banner 禁外链 / 首页结构固定)。 这些断言打的是**真实活栈**:`GET /api/v1/home` 的真实响应,不是常量、不是自造字面量。 """ import pytest pytestmark = pytest.mark.e2e # AGENTS.md 硬规则 #14/#15:首页 8 核心入口固定,顺序不可更改、运营不可重排。 EXPECTED_QUICK_ENTRIES = [ "find_object", # 第一排 "matchmaker", "activities", "counseling", "classroom", # 第二排 "premarital", "anti_fraud", "service_station", ] # INV-016:Banner 仅内部跳转,target_type 白名单(与生产 HomeBannerOperatorController 一致)。 ALLOWED_BANNER_TARGETS = { "activity", "matchmaker", "counseling", "premarital", "service_location", "article", "internal_page", "none", } def test_home_returns_fixed_sections(api, user_token): """规则 #14:首页区块齐备(缺一个即结构被改)。""" data = api.ok("GET", "/home", token=user_token) for key in ("quickEntries", "banners", "userState", "capabilities", "safetyNotice"): assert key in data, f"首页缺少区块 {key},实际 keys={sorted(data.keys())}" def test_quick_entries_fixed_order(api, user_token): """INV-017:8 个核心入口固定且顺序不可更改。""" data = api.ok("GET", "/home", token=user_token) codes = [e.get("code") for e in data["quickEntries"]] assert codes == EXPECTED_QUICK_ENTRIES, f"首页入口顺序被改动:{codes}" def test_banner_target_types_are_internal_only(api, user_token): """INV-016:Banner 不允许外链(target_type 必须落在白名单内)。""" data = api.ok("GET", "/home", token=user_token) banners = data.get("banners") or [] for b in banners: target = b.get("targetType") assert target in ALLOWED_BANNER_TARGETS, f"Banner 出现非白名单 target_type={target!r}"