Merge main into production
This commit is contained in:
@@ -393,6 +393,7 @@ func _test_timer_text_avoids_redundant_frame_updates() -> void:
|
||||
|
||||
func _test_player_runtime_construction() -> void:
|
||||
var host := Control.new()
|
||||
host.size = Vector2(1280, 720)
|
||||
root.add_child(host)
|
||||
var player = load("res://scripts/ui/question_player.gd").new()
|
||||
player.main = host
|
||||
@@ -424,7 +425,29 @@ func _test_player_runtime_construction() -> void:
|
||||
_assert(player.theme_button.icon in [Brand.SUN_ICON, Brand.MOON_ICON], "question theme toggle should use the shared sun or moon icon")
|
||||
_assert(player.choice_badges.size() == 5, "question player should construct an answer badge for every visible choice slot")
|
||||
_assert(player.choice_followup_panels[2].get_parent() == player.choice_rows[2], "distractor remediation should remain nested inside its answer choice")
|
||||
var long_choice := "Transfer to a neurocritical-care center, use a titratable agent to avoid severe hypertension and blood-pressure variability without causing hypotension, start enteral nimodipine, and secure the aneurysm as early as feasible."
|
||||
player.choice_buttons[0].text = long_choice
|
||||
await process_frame
|
||||
await process_frame
|
||||
_assert(player.choice_buttons[0].autowrap_mode == TextServer.AUTOWRAP_WORD_SMART, "long answer choices should use word-smart wrapping")
|
||||
_assert(player.choice_buttons[0].size.y > 68.0, "a wrapped answer choice should grow taller than the standard answer row")
|
||||
_assert(player.choice_buttons[0].size.x <= player.question_panel.size.x, "long answer choices should not widen the question player")
|
||||
_assert(player.next_button.get_global_rect().end.x <= player.get_global_rect().end.x + 0.5, "long answer choices should never push Submit beyond the viewport")
|
||||
var prior_session_kind: String = root.get_node("BlockSessionService").session_kind
|
||||
_assert(root.get_node("BlockSessionService")._simulation_response_is_submitted({"choiceId": "A", "isSubmitted": null}), "legacy answered simulation responses should restore as submitted")
|
||||
_assert(not root.get_node("BlockSessionService")._simulation_response_is_submitted({"choiceId": "A", "isSubmitted": false}), "new simulation drafts should remain editable after an in-session autosave")
|
||||
_assert(not root.get_node("BlockSessionService")._simulation_response_is_submitted({"choiceId": "", "isSubmitted": null}), "legacy skipped simulation responses should remain revisitable")
|
||||
root.get_node("BlockSessionService").session_kind = "simulation"
|
||||
player.presented_choices = [{"id": "A", "text": "First"}, {"id": "B", "text": "Second"}]
|
||||
player.current_answer = {"selected_choice_id": "A", "is_submitted": true}
|
||||
player.selected_choice = "A"
|
||||
player._apply_saved_choice_state()
|
||||
_assert(player.choice_buttons[0].disabled and player.choice_buttons[1].disabled, "resumed submitted simulation answers should lock every choice")
|
||||
_assert(not player.next_button.disabled, "a resumed submitted answer should still allow navigation to the next question")
|
||||
player._select_choice(1)
|
||||
_assert(player.selected_choice == "A", "a resumed submitted simulation answer should not be changeable")
|
||||
player.current_answer = {}
|
||||
player.selected_choice = ""
|
||||
for session_kind in ["block", "core", "bookmark", "review", "simulation"]:
|
||||
root.get_node("BlockSessionService").session_kind = session_kind
|
||||
player._refresh_toolbar_state()
|
||||
|
||||
@@ -15,6 +15,18 @@ func _run() -> void:
|
||||
service.simulation = {"id": "active", "state": "between_blocks", "currentBlock": 2, "totalBlocks": 12, "createdUtc": "2026-07-16T22:04:00Z"}
|
||||
service.history = [{"id": "completed", "state": "completed", "currentBlock": 11, "totalBlocks": 12, "createdUtc": "2026-07-15T20:35:00Z", "predictedScore": 236, "rangeLow": 221, "rangeHigh": 248, "passProbability": 0.82}]
|
||||
service.history_next_cursor = "next-page"
|
||||
_assert(service._is_stale_submit_failure("submit"), "a submit failure after reaching between-block state should be ignored")
|
||||
service.simulation["state"] = "completed"
|
||||
_assert(service._is_stale_submit_failure("submit"), "a submit failure after completion should be ignored")
|
||||
_assert(not service._is_stale_submit_failure("save"), "non-submit failures should still be surfaced")
|
||||
service.simulation["state"] = "block_active"
|
||||
service.submit_recovery_attempts = 0
|
||||
_assert(service._should_reconcile_submit_failure("submit", 409), "an active-block submit conflict should reconcile automatically")
|
||||
service.submit_recovery_attempts = 1
|
||||
_assert(not service._should_reconcile_submit_failure("submit", 409), "submit conflict recovery should be bounded")
|
||||
_assert(not service._should_reconcile_submit_failure("submit", 500), "non-conflict submit failures should still be surfaced")
|
||||
service.submit_recovery_attempts = 0
|
||||
service.simulation["state"] = "between_blocks"
|
||||
var host := Control.new()
|
||||
host.size = Vector2(1400, 800)
|
||||
root.add_child(host)
|
||||
|
||||
Reference in New Issue
Block a user