Files
Jyotisha/tests/test_consultation_domain_registry.py
T
Jesse_ChenandClaude Opus 5.5 5c65834dda feat(consult): split family into parents and children domains (engine still family)
parents (D12, 4/9 houses, Sun/Moon) and children (D7, 5th house, Jupiter,
PK) are plan/card domains with Chinese labels and the brief's aliases. They
send the family route contract to the engine and are rejected as a stored
session theme, so neither Python nor the chat_sessions.theme CHECK changes.
Methodology reports no strict checklist for them; must-use layers follow the
plan domain. Tests with 原值/新值/原因 where assertions changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
2026-09-27 02:54:11 +08:00

114 lines
4.6 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.
#!/usr/bin/env python3
"""Focused tests for the canonical consultation-domain registry."""
from __future__ import annotations
import pytest
from scripts.consultation_domain_registry import (
CANONICAL_DOMAINS,
DEFAULT_THEMES,
DOMAIN_ALIASES,
normalize_domain,
normalize_themes,
)
def test_canonical_domain_registry_is_complete_and_ordered() -> None:
assert CANONICAL_DOMAINS == (
"career",
"marriage",
"wealth",
"health",
"education",
"migration",
"family",
"annual",
"timing",
"general",
)
@pytest.mark.parametrize(
("value", "expected"),
[
("relationship", "marriage"),
("finance", "wealth"),
("money", "wealth"),
("health-pressure", "health"),
("health_pressure", "health"),
("home", "migration"),
("relocation", "migration"),
("varshaphala", "annual"),
],
)
def test_normalize_domain_accepts_required_aliases(value: str, expected: str) -> None:
assert normalize_domain(value) == expected
def test_normalize_themes_accepts_canonical_and_aliases_deduplicated_in_input_order() -> None:
assert normalize_themes(
["timing", "relationship", "marriage", "money", "wealth", "general", "health_pressure"]
) == ["timing", "marriage", "wealth", "general", "health"]
def test_normalize_themes_keeps_product_defaults() -> None:
assert normalize_themes(None) == list(DEFAULT_THEMES)
assert normalize_themes("all") == list(DEFAULT_THEMES)
assert normalize_themes([]) == list(DEFAULT_THEMES)
@pytest.mark.parametrize("value", ["spirituality", "灵性", "unknown-domain"])
def test_normalize_themes_rejects_unknown_domains_instead_of_falling_back(value: str) -> None:
with pytest.raises(ValueError, match="Unknown theme"):
normalize_themes(["career", value])
def test_typescript_registry_matches_python_canonical_domains_and_aliases() -> None:
import json
import re
from pathlib import Path
source = (Path(__file__).resolve().parents[1] / "frontend/src/lib/consultation-domain-registry.ts").read_text()
# 原值:TS 领域 id == Python CANONICAL_DOMAINS,TS 别名表 == DOMAIN_ALIASES。
# 新值:TS 的引擎领域(consultationEngineDomainIds)== CANONICAL_DOMAINS;TS 另有两个
# 只作用于数据卡的子领域 parents / children,引擎侧一律按 family 计算
# (strictWorkflowRoute / workflowThemes 都是 family)。别名比较按「引擎领域」进行:
# Python 认识的每个别名,在 TS 里落到的领域的引擎路由必须等于 Python 的归一结果;
# TS 独有的别名(父母、孩子等)只能落在 parents / children。
# 原因:TASK-consult-evidence-card-20260927 D2,家庭拆父母 / 子女,但不改 Python 引擎。
engine_match = re.search(r"consultationEngineDomainIds = \[([\s\S]*?)\] as const", source)
assert engine_match is not None
assert tuple(re.findall(r'"([^"\n]+)"', engine_match.group(1))) == CANONICAL_DOMAINS
canonical_match = re.search(r"consultationDomainIds = \[([\s\S]*?)\] as const", source)
assert canonical_match is not None
typescript_domains = tuple(re.findall(r'"([^"\n]+)"', canonical_match.group(1)))
card_only = ("parents", "children")
assert tuple(domain for domain in typescript_domains if domain not in card_only) == CANONICAL_DOMAINS
assert set(typescript_domains) - set(CANONICAL_DOMAINS) == set(card_only)
definitions = re.findall(
r'\{ id: "([a-z]+)"[^\n]*?aliases: (\[[^\]]*\]), strictWorkflowRoute: "([a-z]+)", workflowThemes: (\[[^\]]*\])',
source,
)
assert tuple(domain for domain, _aliases, _route, _themes in definitions) == typescript_domains
engine_route: dict[str, str] = {}
typescript_aliases: dict[str, str] = {}
for domain, raw_aliases, route, raw_themes in definitions:
engine_route[domain] = route
if domain in card_only:
assert route == "family" and json.loads(raw_themes) == ["family"], domain
else:
assert route == domain and json.loads(raw_themes) == [domain], domain
for alias in json.loads(raw_aliases):
if alias != domain:
typescript_aliases[alias] = domain
for alias, python_domain in DOMAIN_ALIASES.items():
assert alias in typescript_aliases or alias in typescript_domains, alias
ts_domain = typescript_aliases.get(alias, alias)
assert engine_route[ts_domain] == python_domain, alias
for alias, ts_domain in typescript_aliases.items():
if alias not in DOMAIN_ALIASES:
assert ts_domain in card_only, alias