feat: integrate iFinD data and refine intelligent workspaces
This commit is contained in:
@@ -24,6 +24,8 @@ class FrontendContractTests(unittest.TestCase):
|
||||
cls.html = (STATIC_DIR / "index.html").read_text(encoding="utf-8")
|
||||
cls.script = (STATIC_DIR / "app.js").read_text(encoding="utf-8")
|
||||
cls.ui_core = (STATIC_DIR / "ui-core.js").read_text(encoding="utf-8")
|
||||
cls.design_system = (STATIC_DIR / "design-system.css").read_text(encoding="utf-8")
|
||||
cls.theme = (STATIC_DIR / "theme.css").read_text(encoding="utf-8")
|
||||
collector = IdCollector()
|
||||
collector.feed(cls.html)
|
||||
cls.ids = collector.ids
|
||||
@@ -62,6 +64,13 @@ class FrontendContractTests(unittest.TestCase):
|
||||
):
|
||||
self.assertIn(field, (STATIC_DIR.parent / "screener.py").read_text(encoding="utf-8"))
|
||||
|
||||
def test_wencai_workspace_is_not_exposed_and_mentor_hides_internal_quality_score(self):
|
||||
self.assertNotIn('id="wencaiView"', self.html)
|
||||
self.assertNotIn('data-view="wencaiView"', self.html)
|
||||
for endpoint in ("/api/wencai", "/api/wencai/query", "/api/wencai/saved"):
|
||||
self.assertNotIn(endpoint, self.script)
|
||||
self.assertNotIn("${score}/${total}", self.script)
|
||||
|
||||
def test_auction_navigation_and_frontend_pools_follow_product_order(self):
|
||||
rotation = self.html.index('data-view="rotationView"')
|
||||
auction = self.html.index('data-view="auctionView"')
|
||||
@@ -123,7 +132,7 @@ class FrontendContractTests(unittest.TestCase):
|
||||
def test_shared_ui_core_loads_before_application(self):
|
||||
self.assertLess(
|
||||
self.html.index('<script src="/ui-core.js"'),
|
||||
self.html.index('<script src="/app.js"'),
|
||||
self.html.index('<script src="/app.js'),
|
||||
)
|
||||
for function_name in (
|
||||
"number", "clamp", "escapeHtml", "formatNumber", "formatTimestamp",
|
||||
@@ -158,7 +167,7 @@ class FrontendContractTests(unittest.TestCase):
|
||||
self.assertIn("context.lineTo(x, bodyTop);", candle)
|
||||
self.assertIn("context.moveTo(x, bodyBottom);", candle)
|
||||
self.assertIn("context.lineTo(x, lowY);", candle)
|
||||
self.assertIn("context.fillStyle = CHART_BACKGROUND;", candle)
|
||||
self.assertIn("context.fillStyle = palette.background;", candle)
|
||||
self.assertIn("context.strokeRect(bodyLeft, bodyTop, candleWidth, bodyHeight);", candle)
|
||||
self.assertNotIn("context.lineTo(x, lowY);\n context.stroke();\n const openY", candle)
|
||||
|
||||
@@ -167,7 +176,7 @@ class FrontendContractTests(unittest.TestCase):
|
||||
end = self.script.index("function drawDailyPreviewChart", start)
|
||||
chart = self.script[start:end]
|
||||
self.assertIn("point.average", chart)
|
||||
self.assertIn('context.strokeStyle = "#b7791f";', chart)
|
||||
self.assertIn("context.strokeStyle = palette.average;", chart)
|
||||
self.assertIn('intraday_trade_date || payload.meta?.trade_date', self.script)
|
||||
self.assertIn('(payload.intraday || []).length ? "最新分时 · 1分钟"', self.script)
|
||||
|
||||
@@ -197,6 +206,40 @@ class FrontendContractTests(unittest.TestCase):
|
||||
self.assertIn('state.stockDetailChartMode === "intraday"', self.script)
|
||||
self.assertIn('state.entityDetailChartMode === "intraday"', self.script)
|
||||
|
||||
def test_entity_daily_chart_uses_runtime_theme_palette(self):
|
||||
start = self.script.index("function drawEntityDetailChart")
|
||||
end = self.script.index("function clearEntityDetailChart", start)
|
||||
chart = self.script[start:end]
|
||||
self.assertIn("const palette = currentChartPalette();", chart)
|
||||
self.assertIn("context.fillStyle = palette.background;", chart)
|
||||
self.assertIn("context.fillStyle = palette.axis;", chart)
|
||||
self.assertNotIn('context.fillStyle = "#6c7983";', chart)
|
||||
|
||||
def test_dark_mentor_tokens_and_sentiment_bottom_clearance_are_defined(self):
|
||||
self.assertIn(":root[data-theme=\"dark\"] #mentorView {", self.theme)
|
||||
self.assertIn("--mentor-ink: var(--text-primary);", self.theme)
|
||||
self.assertIn("--mentor-sub: var(--text-secondary);", self.theme)
|
||||
self.assertIn(":root[data-theme=\"dark\"] #mentorView .mentor-message {", self.theme)
|
||||
self.assertIn("border-color: var(--line-soft);", self.theme)
|
||||
self.assertIn("background: var(--surface-subtle);", self.theme)
|
||||
self.assertIn("box-shadow: none;", self.theme)
|
||||
self.assertIn("#sentimentCycleView .sentiment-history-frame {", self.theme)
|
||||
self.assertIn("margin-bottom: var(--card-gap);", self.theme)
|
||||
self.assertIn("padding-bottom: var(--card-gap);", self.theme)
|
||||
self.assertIn("--sentiment-history-max-height:510px;", self.design_system)
|
||||
self.assertIn("max-height:var(--sentiment-history-max-height);", self.design_system)
|
||||
self.assertIn("overflow:auto;", self.design_system)
|
||||
|
||||
def test_theme_switch_is_atomic_and_theme_library_loading_surface_is_dark_safe(self):
|
||||
self.assertIn('typeof document.startViewTransition === "function"', self.script)
|
||||
self.assertIn('root.classList.add("theme-switching")', self.script)
|
||||
self.assertIn('root.classList.remove("theme-switching")', self.script)
|
||||
self.assertIn("clearThemeTransitionEffects();", self.script)
|
||||
self.assertIn("redrawThemeSensitiveVisuals();", self.script)
|
||||
self.assertIn(":root.theme-switching *", self.theme)
|
||||
self.assertIn("::view-transition-old(root)", self.theme)
|
||||
self.assertIn(".theme-detail-empty-v2,", self.theme)
|
||||
|
||||
def test_membership_copy_includes_review_assistant_access(self):
|
||||
self.assertIn("复盘助手仅对会员开放", self.html)
|
||||
self.assertIn("智能选股、问师、问天、复盘助手等智能功能", self.html)
|
||||
|
||||
Reference in New Issue
Block a user