From 3522e85df03bb611412dcabd02762ab6724015eb Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Fri, 2 Oct 2026 14:01:13 +0800 Subject: [PATCH] test(api): yoga list keeps all twelve rows; empty module list is not replaced by a preview (BUG-1186) Regression tests for 96767418 (TASK-upstream-sync4-20261002 T4). Both methods are called unbound; no JyotishAPIHandler is forged. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE --- tests/test_api_yoga_list_presence.py | 64 ++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 tests/test_api_yoga_list_presence.py diff --git a/tests/test_api_yoga_list_presence.py b/tests/test_api_yoga_list_presence.py new file mode 100644 index 00000000..79f2b821 --- /dev/null +++ b/tests/test_api_yoga_list_presence.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +"""BUG-1186 (TASK-upstream-sync4-20261002 T4): the API yoga list is not cut to +ten, and an evaluated empty yoga module is not replaced by a chart preview. + +Both methods read no handler state, so they are called unbound; no +``JyotishAPIHandler`` instance is forged (growth contract). +""" + +from __future__ import annotations + +import os +import sys +import types + +SCRIPTS = os.path.join(os.path.dirname(__file__), '..', 'scripts') +if SCRIPTS not in sys.path: + sys.path.insert(0, SCRIPTS) + +from jyotish_api_server import JyotishAPIHandler # noqa: E402 + + +def _install(monkeypatch, name: str, **attrs) -> None: + module = types.ModuleType(name) + for key, value in attrs.items(): + setattr(module, key, value) + monkeypatch.setitem(sys.modules, name, module) + + +def test_detect_yogas_returns_all_twelve(monkeypatch) -> None: + rows = [{'name': f'Yoga {i}', 'planets': ['Jupiter']} for i in range(12)] + _install(monkeypatch, 'pancha_mahapurusha', detect_pancha_mahapurusha=lambda planets: []) + _install(monkeypatch, 'yoga_expansion', detect_all_yogas=lambda planets, asc: rows) + + result = JyotishAPIHandler._detect_yogas(None, {}, 0) + + # 原值: yogas[:10],第 11、12 条被丢;新值: 12 条全部返回 + assert [row['name'] for row in result] == [f'Yoga {i}' for i in range(12)] + + +def _reading(yoga_module, chart_yogas): + return { + 'chart': {'planets': {'Sun': {}}, 'ascendant': 'Aries', 'yogas': chart_yogas}, + 'modules': {'yoga': yoga_module}, + } + + +def test_evaluated_empty_module_list_is_not_replaced_by_chart_preview() -> None: + preview = [{'name': 'Stale preview yoga'}] + normalized = JyotishAPIHandler._chart_from_full_reading(None, _reading({'yogas': []}, preview)) + assert normalized['yogas'] == [] + + +def test_module_list_precedes_chart_preview_and_detected_yogas_is_second() -> None: + module_rows = [{'name': f'M{i}'} for i in range(12)] + preview = [{'name': 'Stale preview yoga'}] + normalized = JyotishAPIHandler._chart_from_full_reading(None, _reading({'yogas': module_rows}, preview)) + assert normalized['yogas'] == module_rows + + detected = [{'name': 'Detected'}] + normalized = JyotishAPIHandler._chart_from_full_reading(None, _reading({'detected_yogas': detected}, preview)) + assert normalized['yogas'] == detected + + normalized = JyotishAPIHandler._chart_from_full_reading(None, _reading({}, preview)) + assert normalized['yogas'] == preview