项目文件夹

文件
2026-07-13 13:12:33 +08:00

359 行
14 KiB
Python

from __future__ import annotations
from pathlib import Path
APP_JS = Path("src/opensquilla/gateway/static/js/app.js")
OVERVIEW_JS = Path("src/opensquilla/gateway/static/js/views/overview.js")
OVERVIEW_CSS = Path("src/opensquilla/gateway/static/css/views/overview.css")
HEALTH_JS = Path("src/opensquilla/gateway/static/js/views/health.js")
HEALTH_CSS = Path("src/opensquilla/gateway/static/css/views/health.css")
INDEX_HTML = Path("src/opensquilla/gateway/templates/index.html")
VUE_SHARED_ROUTES = Path("opensquilla-webui/src/router/sharedRoutes.ts")
VUE_HEALTH_VIEW = Path("opensquilla-webui/src/views/HealthView.vue")
def test_health_view_is_registered_and_loaded() -> None:
app = APP_JS.read_text(encoding="utf-8")
shared_routes = VUE_SHARED_ROUTES.read_text(encoding="utf-8")
assert "_renderStandardView(HealthView, el)" in app
assert 'data-path="/health"' in app
# The Vue shell folds readiness/doctor into Overview; the /health deep link
# stays valid as a redirect rather than a standalone view.
assert "path: '/health'" in shared_routes
assert "redirect: '/overview'" in shared_routes
assert "HealthView.vue" not in shared_routes
assert not VUE_HEALTH_VIEW.exists()
def test_health_view_calls_doctor_status_and_renders_fix_steps() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
assert "_rpc.call('doctor.status', { agentId: 'main', deep: true })" in source
assert "fixSteps" in source
assert "restartRequired" in source
assert "health-finding" in source
def test_overview_surfaces_readiness_summary() -> None:
source = OVERVIEW_JS.read_text(encoding="utf-8")
assert "doctor.status" in source
assert "ov-health" in source
assert 'data-nav="/health"' in source
def test_overview_humanizes_readiness_status() -> None:
source = OVERVIEW_JS.read_text(encoding="utf-8")
css = OVERVIEW_CSS.read_text(encoding="utf-8")
health_tile_start = source.index('id="ov-health-status"')
health_tile = source[health_tile_start - 120 : health_tile_start + 180]
assert "function _readinessStatusLabel(status)" in source
assert "action_required: 'Action required'" in source
assert "_readinessStatusLabel(report.status ?? 'unknown')" in source
assert "ov-stat__value--mono" not in health_tile
assert "ov-stat__value--status" in health_tile
value_rule = css.split(".ov-stat__value {", 1)[1].split("}", 1)[0]
mono_rule = css.split(".ov-stat__value--mono", 1)[1].split("}", 1)[0]
status_rule = css.split(".ov-stat__value--status", 1)[1].split("}", 1)[0]
assert "line-height: 1.18" in value_rule
assert "line-height: 1.3" in mono_rule
assert "line-height: 1.2" in status_rule
assert "white-space: nowrap" in status_rule
def test_health_css_defines_responsive_finding_rows() -> None:
css = HEALTH_CSS.read_text(encoding="utf-8")
assert ".health-layout" in css
assert ".health-finding" in css
assert "@media (max-width: 760px)" in css
def test_health_mobile_refresh_button_keeps_visible_width() -> None:
css = HEALTH_CSS.read_text(encoding="utf-8")
mobile = css.split("@media (max-width: 760px)", 1)[1]
refresh_rule = mobile.split(".health-stage__header .btn", 1)[1].split("}", 1)[0]
assert "align-self: flex-start" in refresh_rule
assert "width: auto" in refresh_rule
assert "width: 100%" not in refresh_rule
def test_health_status_numerals_have_breathing_room() -> None:
css = HEALTH_CSS.read_text(encoding="utf-8")
score_rule = css.split(".health-score strong {", 1)[1].split("}", 1)[0]
count_rule = css.split(".health-count strong {", 1)[1].split("}", 1)[0]
assert "line-height: 1.12" in score_rule
assert "line-height: 1.12" in count_rule
def test_health_view_uses_status_visual_system() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
css = HEALTH_CSS.read_text(encoding="utf-8")
assert "health-status__rail" in source
assert "health-score" in source
assert "health-finding__dot" in source
assert "health-evidence" in source
assert "health-step__number" in source
assert ".health-status__rail" in css
assert ".health-finding__dot" in css
assert ".health-evidence" in css
assert ".health-step__number" in css
def test_health_view_groups_findings_by_actionability() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
css = HEALTH_CSS.read_text(encoding="utf-8")
assert "Needs action" in source
assert "Degraded capabilities" in source
assert "Optional setup" in source
assert "Ready checks" in source
assert "health-finding-group" in source
assert ".health-finding-group" in css
def test_health_view_keeps_unknown_severity_findings_visible() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
assert "function _findingGroupKind" in source
assert "const impact = _impactValue(finding);" in source
assert "if (impact === 'blocks_ready') return 'action';" in source
assert "if (impact === 'degrades') return 'degraded';" in source
assert "function _impactValue" in source
assert "if (severity === 'warn') return 'degrades';" in source
assert "if (severity === 'info') return 'optional';" in source
assert "return 'none';" in source
def test_health_view_labels_degraded_ready_state_without_hiding_warnings() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
assert "Ready with warnings" in source
assert "if (ready && status === 'degraded')" in source
def test_health_view_fallback_report_uses_readiness_impact_schema() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
assert "impactCounts: { blocks_ready: 1, degrades: 0, optional: 0, none: 0 }" in source
assert "readinessImpact: 'blocks_ready'" in source
assert "gateway.unavailable" in source
def test_health_view_remote_unavailable_does_not_offer_local_start() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
assert "function _gatewayUnavailableFixSteps" in source
assert "function _isLocalGatewayUrl" in source
assert "Run local doctor" in source
assert "Inspect remote gateway" in source
assert "Repair remote deployment" in source
assert "Start local gateway" in source
assert "_gatewayUnavailableFixSteps(gatewayUrl)" in source
assert "opensquilla gateway status --gateway ${_shellArg(gatewayUrl)} --json" in source
assert "opensquilla gateway status --listen ${target.host}" not in source
assert "` --gateway ${_shellArg(gatewayUrl)}`" in source
assert "opensquilla doctor${doctorTarget}${configTarget} --json" in source
def test_health_view_labels_recovery_and_optional_steps_differently() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
css = HEALTH_CSS.read_text(encoding="utf-8")
assert "Recovery steps" in source
assert "Optional setup steps" in source
assert "Recovery requires restart" in source
assert ">Restart required<" not in source
assert "restartRequired</span>" not in source
assert "_stepsHeading" in source
assert "const kind = _findingGroupKind(finding);" in source
assert "_renderSteps(finding.fixSteps || [], kind)" in source
assert ".health-steps__heading" in css
def test_health_view_prioritizes_impact_counts_in_summary_tiles() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
css = HEALTH_CSS.read_text(encoding="utf-8")
assert "const impactCounts = report.impactCounts || _impactCountsFromSeverity" in source
assert "_countTile('Needs action', impactCounts.blocks_ready || 0, 'blocks_ready')" in source
assert "_countTile('Degraded', impactCounts.degrades || 0, 'degrades')" in source
assert "_countTile('Optional', impactCounts.optional || 0, 'optional')" in source
assert "_countTile('Ready', impactCounts.none || 0, 'none')" in source
assert "function _impactCountsFromSeverity" in source
assert ".health-count.is-blocks_ready::before" in css
assert ".health-count.is-degrades::before" in css
assert ".health-count.is-optional::before" in css
assert ".health-count.is-none::before" in css
def test_health_view_surfaces_report_context_for_config_and_agent() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
css = HEALTH_CSS.read_text(encoding="utf-8")
index = INDEX_HTML.read_text(encoding="utf-8")
assert "function _renderReportContext" in source
assert "function _gatewayContextUrl" in source
assert 'data-config-path="{{ config_path }}"' in index
assert "report.gatewayUrl" in source
assert "report.configPath" in source
assert "report.requestedConfigPath" in source
assert "Requested config" in source
assert "report.agentId" in source
assert "health-report-context" in source
assert "health-report-context__item" in source
assert "health-report-context__value" in source
assert ".health-report-context" in css
def test_health_report_context_wraps_long_paths_on_mobile() -> None:
css = HEALTH_CSS.read_text(encoding="utf-8")
source = HEALTH_JS.read_text(encoding="utf-8")
assert "class=\"health-report-context__item\"" in source
assert "class=\"health-report-context__value\"" in source
context_item = css.split(".health-report-context__item", 1)[1].split("}", 1)[0]
context_value = css.split(".health-report-context__value", 1)[1].split("}", 1)[0]
mobile_context = css.split("@media (max-width: 480px)", 1)[1]
mobile_context_item = mobile_context.split(".health-report-context__item", 1)[1].split(
"}", 1
)[0]
assert "display: inline-grid" in context_item
assert "grid-template-columns: auto minmax(0, 1fr)" in context_item
assert "min-width: 0" in context_value
assert "overflow-wrap: anywhere" in context_value
assert "word-break: break-word" in context_value
assert "grid-template-columns: minmax(0, 1fr)" in mobile_context_item
assert "width: 100%" in mobile_context_item
def test_health_runtime_diagnostics_wrap_inside_cards() -> None:
css = HEALTH_CSS.read_text(encoding="utf-8")
wrapping_selectors = (
".health-score__summary",
".health-finding__meta",
".health-finding__title",
".health-finding__detail",
".health-evidence",
".health-evidence span",
".health-step__command",
)
for selector in wrapping_selectors:
rule = css.split(f"{selector} {{", 1)[1].split("}", 1)[0]
assert "min-width: 0" in rule
assert "overflow-wrap: anywhere" in rule
def test_health_view_scopes_local_fallback_commands_to_bootstrap_config() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
assert "function _bootstrapConfigPath" in source
assert "function _usesDefaultGatewayUrl" in source
assert "function _configOption" in source
assert (
"const useConfigTarget = _usesDefaultGatewayUrl(gatewayUrl) "
"&& Boolean(_bootstrapConfigPath());"
) in source
assert (
"const doctorTarget = useConfigTarget ? '' "
": (gatewayUrl ? ` --gateway ${_shellArg(gatewayUrl)}` : '');"
) in source
assert "const targetArgs = useConfigTarget ? '' : bindArgs;" in source
assert "command: `opensquilla doctor${doctorTarget}${configTarget} --json`" in source
assert "command: `opensquilla gateway start${targetArgs}${configTarget}`" in source
assert "command: `opensquilla gateway status${targetArgs} --json${configTarget}`" in source
def test_health_view_treats_ipv6_loopback_gateway_as_local() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
assert "['127.0.0.1', '::1', 'localhost', '0.0.0.0'].includes(target.host)" in source
assert "if (host.startsWith('[') && host.endsWith(']')) host = host.slice(1, -1);" in source
def test_health_view_shows_readiness_impact_as_a_first_class_badge() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
css = HEALTH_CSS.read_text(encoding="utf-8")
assert "function _impactValue" in source
assert "function _impactLabel" in source
assert "class=\"health-impact\"" in source
assert "_impactLabel(impact)" in source
assert "blocks_ready: 'Blocks readiness'" in source
assert ".health-impact" in css
def test_health_view_marks_incomplete_diagnostics_explicitly() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
css = HEALTH_CSS.read_text(encoding="utf-8")
assert "function _findingBadges" in source
assert ".diagnostic.incomplete" in source
assert "Diagnostics incomplete" in source
assert "health-chip--diagnostic" in source
assert ".health-chip--diagnostic" in css
def test_health_view_marks_pending_repairs_explicitly() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
css = HEALTH_CSS.read_text(encoding="utf-8")
assert ".repair.pending" in source
assert "Repair pending" in source
assert "health-chip--repair" in source
assert ".health-chip--repair" in css
def test_health_view_marks_config_mismatch_explicitly() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
css = HEALTH_CSS.read_text(encoding="utf-8")
assert "gateway.config.mismatch" in source
assert "Config mismatch" in source
assert "health-chip--config" in source
assert ".health-chip--config" in css
def test_health_view_formats_evidence_for_operator_readability() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
assert "function _visibleEvidenceEntries" in source
assert "function _evidenceLabel" in source
assert "restart_required" in source
assert "replace(/([a-z0-9])([A-Z])/g" in source
def test_health_view_makes_recovery_commands_copyable() -> None:
source = HEALTH_JS.read_text(encoding="utf-8")
css = HEALTH_CSS.read_text(encoding="utf-8")
assert "data-health-copy-command" in source
assert "navigator.clipboard.writeText" in source
assert "Copied command" in source
assert "health-step__copy" in source
assert ".health-step__copy" in css
copy_start = css.index(".health-step__copy {")
copy_rule = css[copy_start : css.index("}", copy_start)]
assert "height: 40px" in copy_rule
assert "width: 40px" in copy_rule
mobile_start = css.index("@media (max-width: 480px)")
mobile_css = css[mobile_start:]
command_start = mobile_css.index(".health-step__command {")
command_rule = mobile_css[command_start : mobile_css.index("}", command_start)]
command_code_start = mobile_css.index(".health-step__command code {")
command_code_rule = mobile_css[
command_code_start : mobile_css.index("}", command_code_start)
]
assert "width: 100%" in command_rule
assert "flex: 1 1 auto" in command_code_rule
assert "min-width: 0" in command_code_rule