Files
step3/tests/ccs_player_test.gd
T
2026-07-23 04:43:02 -05:00

125 lines
5.8 KiB
GDScript

extends SceneTree
var failures := 0
var ccs_service
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
ccs_service = root.get_node("CCSService")
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", "header should show the readable location")
_assert(player.action_buttons.size() == 4, "CCS workspace should expose four persistent clinical tasks")
_assert(player.tabs.get_tab_count() == 7, "CCS chart should expose seven predictable tabs")
_assert(player.tabs.get_tab_title(0) == "Order Sheet", "the first chart tab should be the order sheet")
_assert(player.allotted_label.text.contains("18 minutes + 2 minutes"), "20-minute cases should reserve two final-order minutes")
_assert(player.active_orders.get_child_count() == 1, "active orders should render as structured rows")
_assert(player._ordered_vital_keys(ccs_service.attempt.vitals) == ["temperature", "bloodPressure", "pulse", "respirations", "oxygenSaturation"], "vitals should use clinical priority order")
_assert(player._chart_entries("lab").size() == 1, "categorized results should render in their assigned tab")
_assert(player._simulated_time_text(60).contains("10:00 AM"), "simulated time should derive from the case start")
_assert(not player.opening_active, "completed opening flows should not replay on resume")
_assert(not player.final_orders_notice.visible, "active cases should not show final-order instructions")
var clerk_font_size: int = player.search.get_theme_font_size("font_size")
var original_size: int = player.clinical_labels[0].get_theme_font_size("normal_font_size")
var prior_profile_api_url: String = ProjectSettings.get_setting("step3/profile_api_url", "")
ProjectSettings.set_setting("step3/profile_api_url", "http://127.0.0.1:1")
player._zoom(ccs_service.TEXT_SCALE_STEP)
ProjectSettings.set_setting("step3/profile_api_url", prior_profile_api_url)
_assert(player.clinical_labels[0].get_theme_font_size("normal_font_size") > original_size, "clinical text zoom should remain available")
_assert(player.search.get_theme_font_size("font_size") == clerk_font_size, "clinical text zoom should not resize order controls")
player._stage_order("bmp")
_assert(player.staged_order_codes == ["bmp"], "orders should stage before submission")
_assert(not player.commit_orders_button.disabled, "staged orders should enable confirmation")
player._clear_staged_orders()
_assert(player.commit_orders_button.disabled, "clearing staged orders should disable confirmation")
player.size = Vector2(800, 900)
player._update_responsive_layout()
_assert(player.action_grid.columns == 2, "narrow CCS screens should use a two-column action workspace")
ccs_service.attempt.state = "final_orders"
player._render()
_assert(player.final_orders_notice.visible, "final-orders mode should show instructions")
_assert(player.exit_button.text == "Submit Final Orders", "final-orders mode should expose final submission")
_assert(player.action_buttons[0].disabled and not player.action_buttons[1].disabled, "only order review should remain available in final orders")
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:
var now := Time.get_unix_time_from_system()
return {
"id": "attempt-1",
"state": "active",
"revision": 1,
"openingCompleted": true,
"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.",
"historySections": [{"code": "hpi", "title": "History of present illness", "text": "She stopped insulin when oral intake declined."}],
"appearance": "She is lethargic but arousable.",
"simulatedStartUtc": "2026-07-15T09:00:00Z",
"simulatedMinute": 0,
"realTimeMinutes": 20,
"createdUtc": Time.get_datetime_string_from_unix_time(now - 60, true),
"deadlineUtc": Time.get_datetime_string_from_unix_time(now + 1020, true),
"hardDeadlineUtc": Time.get_datetime_string_from_unix_time(now + 1140, true),
"vitals": {
"oxygenSaturation": "98% on room air",
"pulse": "118/min",
"temperature": "37.3 C (99.1 F)",
"respirations": "28/min",
"bloodPressure": "88/56 mm Hg"
},
"vitalHistory": [{"simulatedMinute": 0, "values": {"pulse": "118/min"}}],
"chart": [
{"simulatedMinute": 0, "category": "progress", "code": "reason", "title": "Reason for encounter", "text": "Initial evaluation."},
{"simulatedMinute": 12, "category": "lab", "code": "bmp", "title": "Basic metabolic panel", "text": "Glucose 580 mg/dL."}
],
"activeOrderCodes": ["normal_saline_bolus"],
"activeOrders": [{
"code": "normal_saline_bolus", "name": "0.9% sodium chloride intravenous bolus",
"category": "medication", "route": "IV", "frequency": "Once",
"orderedMinute": 0, "reportMinute": 0
}],
"availableExams": [
{"code": "general", "name": "General and hydration examination", "durationMinutes": 1},
{"code": "neurologic", "name": "Neurologic examination", "durationMinutes": 1}
],
"allowedLocations": ["emergency_department", "icu"]
}
func _assert(condition: bool, message: String) -> void:
if condition:
return
failures += 1
push_error(message)