diff --git a/frontend2/src/pages/play/components/play-action-jump.tsx b/frontend2/src/pages/play/components/play-action-jump.tsx index 5c9a3721..21321b2d 100644 --- a/frontend2/src/pages/play/components/play-action-jump.tsx +++ b/frontend2/src/pages/play/components/play-action-jump.tsx @@ -34,7 +34,6 @@ export function PlayActionJumpButton({ animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: 12 }} transition={transitions.snap} - onPointerDown={onClick} onClick={onClick} aria-label={t("play.action_jump_title")} title={t("play.action_jump_title")} diff --git a/frontend2/src/shared/ui/header.tsx b/frontend2/src/shared/ui/header.tsx index cdb0df0d..93d462b7 100644 --- a/frontend2/src/shared/ui/header.tsx +++ b/frontend2/src/shared/ui/header.tsx @@ -18,7 +18,6 @@ export function Header({ const { lang, setLang, t } = useLanguage() const [menuOpen, setMenuOpen] = useState(false) const accountName = auth.user?.display_name?.trim() || "reader" - const accountInitial = accountName.slice(0, 1).toUpperCase() const accountLabel = t("header.account") const handleLogin = () => { @@ -61,9 +60,6 @@ export function Header({ aria-expanded={menuOpen} title={accountName} > - - {accountInitial} - {accountLabel} {menuOpen ? ( diff --git a/tests/test_author_product_api.py b/tests/test_author_product_api.py index e65bd296..96903557 100644 --- a/tests/test_author_product_api.py +++ b/tests/test_author_product_api.py @@ -582,6 +582,24 @@ def test_author_job_service_loading_cards_are_stage_adaptive() -> None: import rpg_backend.author.jobs as jobs_module service = AuthorJobService() + settings = get_settings() + uncached_input_tokens = max(240 - 160 - 30, 0) + estimated_cost_rmb = ( + uncached_input_tokens * settings.responses_input_price_per_million_tokens_rmb / 1_000_000 + + 160 + * settings.responses_input_price_per_million_tokens_rmb + / 1_000_000 + * settings.responses_session_cache_hit_multiplier + + 30 + * settings.responses_input_price_per_million_tokens_rmb + / 1_000_000 + * settings.responses_session_cache_creation_multiplier + + 60 * settings.responses_output_price_per_million_tokens_rmb / 1_000_000 + ) + estimated_cost_usd = round(estimated_cost_rmb, 6) * settings.responses_usd_per_rmb + + def expected_token_budget(total_tokens: int) -> str: + return f"{total_tokens} total tokens · USD {estimated_cost_usd:.6f} est." def build_record(stage: str, stage_index: int, total_tokens: int | None) -> jobs_module._AuthorJobRecord: metrics = None @@ -622,7 +640,7 @@ def build_record(stage: str, stage_index: int, total_tokens: int | None) -> jobs 225, {"theme", "structure", "working_title", "tone", "story_premise", "story_stakes", "generation_status", "token_budget"}, "Story frame drafted. Title, premise, and stakes are set.", - "225 total tokens · USD 0.000020 est.", + expected_token_budget(225), ), ( "cast_ready", @@ -630,7 +648,7 @@ def build_record(stage: str, stage_index: int, total_tokens: int | None) -> jobs 300, {"theme", "structure", "working_title", "tone", "story_premise", "story_stakes", "cast_count", "cast_anchor", "generation_status", "token_budget"}, "Cast roster drafted. NPC tensions are in place.", - "300 total tokens · USD 0.000020 est.", + expected_token_budget(300), ), ( "beat_plan_ready", @@ -638,7 +656,7 @@ def build_record(stage: str, stage_index: int, total_tokens: int | None) -> jobs 360, {"theme", "structure", "working_title", "tone", "story_premise", "story_stakes", "cast_count", "cast_anchor", "beat_count", "opening_beat", "final_beat", "generation_status", "token_budget"}, "Beat plan drafted. Main progression is mapped.", - "360 total tokens · USD 0.000020 est.", + expected_token_budget(360), ), ( "completed", @@ -646,7 +664,7 @@ def build_record(stage: str, stage_index: int, total_tokens: int | None) -> jobs 570, {"theme", "structure", "working_title", "tone", "story_premise", "story_stakes", "cast_count", "cast_anchor", "beat_count", "opening_beat", "final_beat", "generation_status", "token_budget"}, "Bundle complete. Story package is ready.", - "570 total tokens · USD 0.000020 est.", + expected_token_budget(570), ), ] diff --git a/tests/test_navigation_mental_model_contract.py b/tests/test_navigation_mental_model_contract.py index a2940727..45a775f3 100644 --- a/tests/test_navigation_mental_model_contract.py +++ b/tests/test_navigation_mental_model_contract.py @@ -1110,6 +1110,8 @@ def test_home_topbar_account_ia_keeps_creation_in_hero() -> None: assert "topbar-account__label" in header assert "topbar-lang" in header assert "topbar-account" in header + assert "accountInitial" not in header + assert 'className="topbar-account__avatar"' not in header assert '"header.account": "Account"' in strings assert '"header.account": "账号"' in strings diff --git a/tests/test_play_direction_a_editorial_primitives_contract.py b/tests/test_play_direction_a_editorial_primitives_contract.py index 8b361916..ccd9141f 100644 --- a/tests/test_play_direction_a_editorial_primitives_contract.py +++ b/tests/test_play_direction_a_editorial_primitives_contract.py @@ -2550,7 +2550,8 @@ def test_play_has_jump_to_action_affordance_when_choices_are_below_viewport() -> assert "data-play-action-jump-stage={stage}" in action_jump assert 'data-play-action-jump-compact={compactJump ? "true" : "false"}' in action_jump assert 'data-play-action-jump-detail="true"' in action_jump - assert "onPointerDown={onClick}" in action_jump + assert "onPointerDown={onClick}" not in action_jump + assert "onClick={onClick}" in action_jump assert "isPlayElementAwayFromViewport" in action_jump_utils assert "scrollToPlayActionArea" in action_jump_utils assert "scrollToPlayImpactSummaryOrAction" in action_jump_utils