It checked for a "DynamicQuestionsIcon" mode card that no longer exists in study_selector.gd (that mode moved to its own nav item and screen a while back), so it always failed. CCS Cases is now also UAT-gated and won't be present in the default test environment either, so point the check at Question Bank, the one mode card that's always rendered.
109 lines
7.2 KiB
GDScript
109 lines
7.2 KiB
GDScript
extends SceneTree
|
|
|
|
var failures := 0
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("_run")
|
|
|
|
|
|
func _run() -> void:
|
|
var host := Control.new()
|
|
host.size = Vector2(240, 720)
|
|
root.add_child(host)
|
|
var selector = load("res://scripts/ui/study_selector.gd").new()
|
|
selector.size = host.size
|
|
host.add_child(selector)
|
|
await process_frame
|
|
selector._show_stage("step3")
|
|
selector._refresh_grid_columns()
|
|
await process_frame
|
|
|
|
_assert(selector.stage_scroll != null, "study selection should scroll vertically on short web viewports")
|
|
_assert(selector.stage_scroll.horizontal_scroll_mode == ScrollContainer.SCROLL_MODE_DISABLED, "study selection should never introduce horizontal scrolling")
|
|
_assert(selector.mode_grid.columns == 1, "phone-width mode cards should use one column")
|
|
_assert(selector.stage_content.get_combined_minimum_size().x <= host.size.x, "phone-width study content should fit inside the web canvas (minimum %.1f px)" % selector.stage_content.get_combined_minimum_size().x)
|
|
for card in selector.responsive_cards:
|
|
_assert(card.custom_minimum_size.x == 0.0, "phone-width cards should release their desktop minimum width")
|
|
for row in selector.responsive_card_rows:
|
|
_assert(row.vertical, "phone-width card content should stack instead of clipping")
|
|
_assert(selector.mode_view.find_children("*", "RichTextLabel", true, false).is_empty(), "study modes should not render the legacy rich-text simulation note")
|
|
var question_bank_icon := selector.mode_view.find_child("QuestionBankIcon", true, false) as TextureRect
|
|
_assert(question_bank_icon != null, "question bank should expose its mode icon")
|
|
if question_bank_icon != null:
|
|
_assert(question_bank_icon.texture.resource_path == "res://assets/icons/lucide/clipboard-list.svg", "question bank should use a web-safe vector icon")
|
|
selector._show_stage("question_bank")
|
|
await process_frame
|
|
_assert(selector.question_bank_launch_view.visible and not selector.mode_view.visible, "direct question bank navigation should show only the focused launch state")
|
|
_assert(selector.launch_retry_button != null and selector.launch_error_label != null, "question bank launch should retain retry and error controls")
|
|
|
|
var main_screen = load("res://scripts/ui/main.gd").new()
|
|
main_screen.size = host.size
|
|
host.add_child(main_screen)
|
|
await process_frame
|
|
main_screen._update_responsive_layout()
|
|
_assert(main_screen.screens.has("dashboard"), "the authenticated shell should include the dashboard screen")
|
|
_assert(main_screen.theme_button.custom_minimum_size == Vector2(44, 44), "the theme toggle should keep a stable square footprint")
|
|
_assert(main_screen.theme_button.size.x >= 44.0 and main_screen.theme_button.size.y >= 44.0, "the theme toggle should not collapse into an oval")
|
|
_assert(main_screen.theme_button.icon_alignment == HORIZONTAL_ALIGNMENT_CENTER, "the theme toggle icon should remain centered")
|
|
_assert(main_screen.theme_button.get_index() < main_screen.account_button.get_index(), "the theme toggle should appear before the account dropdown")
|
|
_assert(main_screen.account_chevron_button.get_index() == main_screen.account_button.get_index() + 1, "the account avatar and chevron should remain adjacent")
|
|
_assert(main_screen.header_panel.find_child("HeaderStats", true, false) == null, "the application header should not display rating or role labels")
|
|
var pause_menu_has_profile := false
|
|
for menu_button in main_screen.app_menu.find_children("*", "Button", true, false):
|
|
if menu_button.text == "Profile":
|
|
pause_menu_has_profile = true
|
|
_assert(not pause_menu_has_profile, "the paused-run menu should not duplicate profile navigation")
|
|
_assert(main_screen.session_expiry_dialog != null, "the application shell should construct a global session-expiry prompt")
|
|
main_screen.session_expiry_dialog._show_warning(120)
|
|
_assert(main_screen.session_expiry_dialog.visible, "the session-expiry prompt should cover every authenticated screen")
|
|
_assert(main_screen.session_expiry_dialog.message_label.text.contains("02:00"), "the session-expiry prompt should display a live countdown")
|
|
main_screen.session_expiry_dialog._refresh_started()
|
|
_assert(main_screen.session_expiry_dialog.stay_button.disabled, "the renewal action should lock while a refresh request is active")
|
|
main_screen.session_expiry_dialog._refresh_failed("Connection interrupted.", false)
|
|
_assert(not main_screen.session_expiry_dialog.stay_button.disabled, "a transient renewal failure should permit retry before expiry")
|
|
var cancel_event := InputEventAction.new()
|
|
cancel_event.action = "ui_cancel"
|
|
cancel_event.pressed = true
|
|
main_screen.session_expiry_dialog._unhandled_input(cancel_event)
|
|
_assert(main_screen.session_expiry_dialog.visible, "the session-expiry prompt should not be dismissible with Escape")
|
|
main_screen.session_expiry_dialog.dismiss_for_logout()
|
|
_assert(not main_screen.account_chevron_button.visible, "nonessential account controls should collapse on phone-width headers")
|
|
var question_bank_nav := main_screen.sidebar.find_child("NavQuestionBank", true, false) as Button
|
|
_assert(question_bank_nav != null and question_bank_nav.text == "Question Bank", "the Practice navigation item should be replaced by Question Bank")
|
|
_assert(main_screen.sidebar.find_child("NavPractice", true, false) == null, "the sidebar should not retain a Practice navigation item")
|
|
var profile_nav := main_screen.sidebar.find_child("NavPerformance", true, false) as Button
|
|
var settings_nav := main_screen.sidebar.find_child("NavSettings", true, false) as Button
|
|
var donation_nav := main_screen.sidebar.find_child("NavDonations", true, false) as Button
|
|
_assert(donation_nav != null and donation_nav.text == "Support RanaZe", "the shell should expose donation navigation")
|
|
_assert(profile_nav != null and settings_nav != null and profile_nav.get_index() + 1 == settings_nav.get_index(), "Profile should sit directly above Settings in the lower navigation group")
|
|
var theme_service = root.get_node("UIThemeService")
|
|
var prior_dark_mode: bool = theme_service.is_dark_mode()
|
|
theme_service.set_dark_mode(true)
|
|
await process_frame
|
|
theme_service.set_dark_mode(false)
|
|
await process_frame
|
|
var dashboard = main_screen.screens.get("dashboard")
|
|
var dashboard_card := dashboard.metric_grid.get_parent() as PanelContainer
|
|
var dashboard_box := dashboard_card.get_theme_stylebox("panel") as StyleBoxFlat
|
|
_assert(dashboard_box.bg_color.is_equal_approx(Color.WHITE), "dashboard cards should remain light after the shell refresh")
|
|
var simulations = main_screen.screens.get("simulation_history")
|
|
var simulation_box := simulations.active_section.get_theme_stylebox("panel") as StyleBoxFlat
|
|
_assert(simulation_box.bg_color.is_equal_approx(simulations._section_box(false).bg_color), "exam simulation panels should remain light after the shell refresh")
|
|
var notes_screen = main_screen.screens.get("notes")
|
|
var notes_box := notes_screen.notes_editor.editor.get_theme_stylebox("normal") as StyleBoxFlat
|
|
_assert(notes_box.bg_color.is_equal_approx(Color.WHITE), "the Notes editor should remain light after the shell refresh")
|
|
theme_service.set_dark_mode(prior_dark_mode)
|
|
await process_frame
|
|
|
|
host.queue_free()
|
|
await process_frame
|
|
quit(1 if failures > 0 else 0)
|
|
|
|
|
|
func _assert(condition: bool, message: String) -> void:
|
|
if condition:
|
|
return
|
|
failures += 1
|
|
push_error(message)
|