142 lines
6.8 KiB
GDScript
142 lines
6.8 KiB
GDScript
extends SceneTree
|
|
|
|
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 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")
|
|
_assert(player.intro_dialog.theme != null, "CCS dialogs should receive an explicit readable theme")
|
|
_assert(player.intro_dialog.theme.get_color("font_color", "Label") == Brand.text_color(player.theme_service.is_dark_mode()), "CCS dialog text should contrast with the active theme")
|
|
player.time_dialog.popup_centered(Vector2i(600, 350))
|
|
await process_frame
|
|
_assert(player.time_dialog.visible, "CCS dialog lifecycle test should begin with an open popup")
|
|
player.on_hide()
|
|
_assert(not player.time_dialog.visible, "hiding the CCS screen should dismiss popup windows")
|
|
player.visible = false
|
|
ccs_service.attempt.openingCompleted = false
|
|
player._render()
|
|
await process_frame
|
|
_assert(not player.intro_dialog.visible, "a hidden classic player must not open dialogs over CCS Cases 2")
|
|
_assert(not player.opening_active, "a hidden classic player must not begin its opening sequence")
|
|
|
|
player.visible = true
|
|
ccs_service.attempt.openingCompleted = true
|
|
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)
|