Files
step3/tests/ccs_player_test.gd
2026-07-16 22:42:03 -05:00

125 lines
6.0 KiB
GDScript

extends SceneTree
const Style := preload("res://scripts/ui/ui_style.gd")
const Brand := preload("res://scripts/ui/medmind_style.gd")
var failures := 0
var ccs_service
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
ccs_service = root.get_node("CCSService")
var theme_service = root.get_node("UIThemeService")
var prior_dark_mode: bool = theme_service.is_dark_mode()
var prior_attempt: Dictionary = ccs_service.attempt.duplicate(true)
var prior_orders: Array = ccs_service.orders.duplicate(true)
var prior_scale: float = ccs_service.text_scale
ccs_service.text_scale = 1.0
ccs_service.orders = []
ccs_service.attempt = _sample_attempt()
var host := Control.new()
host.size = Vector2(1440, 900)
root.add_child(host)
var player = load("res://scripts/ui/ccs_player.gd").new()
player.main = host
player.size = host.size
host.add_child(player)
await process_frame
player._render()
await process_frame
_assert(player.heading.text == "CCS Case | Emergency Department", "CCS header should show the readable location without a case id")
_assert(player._ordered_vital_keys(ccs_service.attempt.vitals) == ["temperature", "bloodPressure", "pulse", "respirations", "oxygenSaturation"], "vital chips should use the clinical priority order")
_assert(player.vitals_flow.get_child_count() == 5, "every supplied vital should render as a chip")
_assert(player.search_button.icon != null, "Order Clerk search should use a bundled icon rather than a font glyph")
_assert(player.summary.get_meta("ccs_region", "") == "summary", "summary highlighting should use its own region")
_assert(player.history.get_meta("ccs_region", "") == "history", "history highlighting should use its own region")
_assert(player.appearance.get_meta("ccs_region", "") == "appearance", "appearance highlighting should use its own region")
_assert(player.chart.get_meta("ccs_region", "") == "chart", "chart highlighting should use its own region")
_assert(not player.workspace.vertical, "wide CCS screens should use chart and Order Clerk columns")
_assert(player.orders.get_child_count() == 1, "active orders should render in the Order Clerk")
var active_order_row := player.orders.get_child(0) as HBoxContainer
var active_order_label := active_order_row.get_child(0) as Label
_assert(active_order_label.text == "Normal Saline Bolus", "internal order codes should be human readable")
_assert(player.actions.get_child_count() == 2, "available physical examinations should render as actions")
_assert(player.locations.get_child_count() == 2, "allowed locations should render as move actions")
_assert(not player.clock.visible, "the normal active-case countdown should remain hidden")
var clerk_font_size: int = player.search.get_theme_font_size("font_size")
var chart_font_size: int = player.summary.get_theme_font_size("normal_font_size")
player._zoom(ccs_service.TEXT_SCALE_STEP)
_assert(player.summary.get_theme_font_size("normal_font_size") > chart_font_size, "text zoom should enlarge clinical chart text")
_assert(player.search.get_theme_font_size("font_size") == clerk_font_size, "text zoom should not resize Order Clerk controls")
player.size = Vector2(800, 900)
player._update_responsive_layout()
_assert(player.workspace.vertical, "narrow CCS screens should stack the Order Clerk below the chart")
ccs_service.attempt.state = "final_orders"
ccs_service.attempt.finalOrdersDeadlineUtc = Time.get_datetime_string_from_unix_time(Time.get_unix_time_from_system() + 90.0, true)
player._render()
_assert(player.final_orders_notice.visible and player.clock.visible, "final-orders mode should show instructions and its deadline")
_assert(not player.time_row.visible, "time advancement should be unavailable during final orders")
theme_service.set_dark_mode(true)
await process_frame
theme_service.set_dark_mode(false)
Style.refresh_tree(player, true)
await process_frame
var light_panel := player.chart_panel.get_theme_stylebox("panel") as StyleBoxFlat
_assert(light_panel.bg_color.is_equal_approx(Brand.content_card_box(false, false).bg_color), "CCS light styles should win after the shell palette translation")
_assert(player.summary.get_theme_color("default_color").is_equal_approx(Brand.text_color(false)), "CCS light chart text should remain readable")
theme_service.set_dark_mode(true)
Style.refresh_tree(player, false)
await process_frame
var dark_panel := player.chart_panel.get_theme_stylebox("panel") as StyleBoxFlat
_assert(dark_panel.bg_color.is_equal_approx(Brand.content_card_box(true, false).bg_color), "CCS dark styles should win after the shell palette translation")
_assert(player.summary.get_theme_color("default_color").is_equal_approx(Brand.text_color(true)), "CCS dark chart text should remain readable")
theme_service.set_dark_mode(prior_dark_mode)
await process_frame
host.queue_free()
await process_frame
ccs_service.attempt = prior_attempt
ccs_service.orders = prior_orders
ccs_service.text_scale = prior_scale
quit(1 if failures > 0 else 0)
func _sample_attempt() -> Dictionary:
return {
"id": "attempt-1",
"state": "active",
"location": "emergency_department",
"patientSummary": "24-year-old woman with type 1 diabetes mellitus",
"reasonForEncounter": "Two days of vomiting and progressive lethargy.",
"history": "She stopped insulin when oral intake declined.",
"appearance": "She is lethargic but arousable.",
"vitals": {
"oxygenSaturation": "98% on room air",
"pulse": "118/min",
"temperature": "37.3 C (99.1 F)",
"respirations": "28/min",
"bloodPressure": "88/56 mm Hg"
},
"chart": [{"simulatedMinute": 0, "category": "progress", "text": "Initial evaluation is in progress."}],
"activeOrderCodes": ["normal_saline_bolus"],
"availableExams": [
{"code": "general", "name": "General and hydration examination"},
{"code": "neurologic", "name": "Neurologic examination"}
],
"allowedLocations": ["emergency_department", "icu"],
"deadlineUtc": Time.get_datetime_string_from_unix_time(Time.get_unix_time_from_system() + 600.0, true)
}
func _assert(condition: bool, message: String) -> void:
if condition:
return
failures += 1
push_error(message)