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" 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