Compare commits

...

6 Commits

4 changed files with 111 additions and 43 deletions
-5
View File
@@ -89,10 +89,6 @@ visible = false
placeholder_text = "Date of Birth (YYYY-MM-DD)" placeholder_text = "Date of Birth (YYYY-MM-DD)"
size_flags_horizontal = 3 size_flags_horizontal = 3
[node name="ModeToggle" type="CheckButton" parent="CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox"]
layout_mode = 1
text = "Register"
[node name="AuthButton" type="Button" parent="CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox"] [node name="AuthButton" type="Button" parent="CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox"]
layout_mode = 1 layout_mode = 1
text = "Login" text = "Login"
@@ -125,7 +121,6 @@ size_flags_horizontal = 4
[connection signal="pressed" from="CenterContainer/VBoxContainer/AuthButtonsRow/RegisterButton" to="." method="_on_register_button_pressed"] [connection signal="pressed" from="CenterContainer/VBoxContainer/AuthButtonsRow/RegisterButton" to="." method="_on_register_button_pressed"]
[connection signal="pressed" from="CenterContainer/VBoxContainer/PlayButton" to="." method="_on_play_button_pressed"] [connection signal="pressed" from="CenterContainer/VBoxContainer/PlayButton" to="." method="_on_play_button_pressed"]
[connection signal="pressed" from="CenterContainer/VBoxContainer/QuitButton" to="." method="_on_quit_button_pressed"] [connection signal="pressed" from="CenterContainer/VBoxContainer/QuitButton" to="." method="_on_quit_button_pressed"]
[connection signal="toggled" from="CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/ModeToggle" to="." method="_on_mode_toggle_toggled"]
[connection signal="pressed" from="CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/AuthButton" to="." method="_on_auth_button_pressed"] [connection signal="pressed" from="CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/AuthButton" to="." method="_on_auth_button_pressed"]
[connection signal="text_submitted" from="CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/UsernameEdit" to="." method="_on_auth_button_pressed"] [connection signal="text_submitted" from="CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/UsernameEdit" to="." method="_on_auth_button_pressed"]
[connection signal="text_submitted" from="CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/PasswordEdit" to="." method="_on_auth_button_pressed"] [connection signal="text_submitted" from="CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/PasswordEdit" to="." method="_on_auth_button_pressed"]
+23 -26
View File
@@ -3,14 +3,15 @@ extends Control
## ##
## The AuthPanel is hidden by default. When the user clicks the LoginButton or ## The AuthPanel is hidden by default. When the user clicks the LoginButton or
## RegisterButton (AuthButtonsRow, above the panel), the auth panel slides in. ## RegisterButton (AuthButtonsRow, above the panel), the auth panel slides in.
## The ModeToggle switches between Login and Register modes, showing/hiding ## The Login and Register buttons on the AuthButtonsRow directly set the panel's
## the email and DOB fields accordingly. ## mode, so the user can switch between Login and Register at any time while
## the panel is open.
## ##
## On successful auth the token is stored via ApiClient, AuthButtonsRow hides, ## On successful auth the token is stored via ApiClient, AuthButtonsRow hides,
## the welcome label shows the username, and the Play button becomes enabled. ## the welcome label shows the username, and the Play button becomes enabled.
## The auth form fields are hidden, leaving only the welcome message visible.
# ─── UI references ────────────────────────────────────────────────────────────
# ── UI references ────────────────────────────────────────────────────────────
var _auth_buttons_row: HBoxContainer var _auth_buttons_row: HBoxContainer
var _login_button: Button var _login_button: Button
@@ -21,7 +22,6 @@ var _username_edit: LineEdit
var _password_edit: LineEdit var _password_edit: LineEdit
var _email_edit: LineEdit var _email_edit: LineEdit
var _dob_edit: LineEdit var _dob_edit: LineEdit
var _mode_toggle: CheckButton
var _auth_button: Button var _auth_button: Button
var _status_label: Label var _status_label: Label
var _welcome_label: Label var _welcome_label: Label
@@ -32,7 +32,7 @@ var _is_register_mode: bool = false
var _is_authenticating: bool = false var _is_authenticating: bool = false
# ── Lifecycle ──────────────────────────────────────────────────────────────── # ─── Lifecycle ────────────────────────────────────────────────────────────────
func _ready() -> void: func _ready() -> void:
# Cache node references. # Cache node references.
@@ -45,7 +45,6 @@ func _ready() -> void:
_password_edit = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/PasswordEdit _password_edit = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/PasswordEdit
_email_edit = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/EmailEdit _email_edit = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/EmailEdit
_dob_edit = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/DOBEdit _dob_edit = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/DOBEdit
_mode_toggle = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/ModeToggle
_auth_button = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/AuthButton _auth_button = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/AuthButton
_status_label = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/AuthStatusLabel _status_label = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/AuthStatusLabel
_welcome_label = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/WelcomeLabel _welcome_label = $CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/WelcomeLabel
@@ -62,7 +61,7 @@ func _ready() -> void:
_update_auth_mode_ui() _update_auth_mode_ui()
# ── Play / Quit ────────────────────────────────────────────────────────────── # ─── Play / Quit ──────────────────────────────────────────────────────────────
func _on_play_button_pressed() -> void: func _on_play_button_pressed() -> void:
if _play_button.disabled: if _play_button.disabled:
@@ -76,11 +75,14 @@ func _on_quit_button_pressed() -> void:
get_tree().quit() get_tree().quit()
# ── Auth panel toggle ──────────────────────────────────────────────────────── # ─── Auth panel toggle ────────────────────────────────────────────────────────
func _on_login_button_pressed() -> void: func _on_login_button_pressed() -> void:
"""Show the auth panel, called from AuthButtonsRow/LoginButton.""" """Show the auth panel in login mode, called from AuthButtonsRow/LoginButton."""
_auth_panel.visible = true _auth_panel.visible = true
_is_register_mode = false
_update_auth_mode_ui()
_clear_status()
_username_edit.grab_focus() _username_edit.grab_focus()
@@ -88,20 +90,11 @@ func _on_register_button_pressed() -> void:
"""Show the auth panel in register mode, called from AuthButtonsRow/RegisterButton.""" """Show the auth panel in register mode, called from AuthButtonsRow/RegisterButton."""
_auth_panel.visible = true _auth_panel.visible = true
_is_register_mode = true _is_register_mode = true
_mode_toggle.button_pressed = true
_update_auth_mode_ui() _update_auth_mode_ui()
_clear_status() _clear_status()
_username_edit.grab_focus() _username_edit.grab_focus()
# ── Mode toggle (Login / Register) ───────────────────────────────────────────
func _on_mode_toggle_toggled(button_pressed: bool) -> void:
_is_register_mode = button_pressed
_update_auth_mode_ui()
_clear_status()
func _update_auth_mode_ui() -> void: func _update_auth_mode_ui() -> void:
"""Update labels and field visibility based on login vs register mode.""" """Update labels and field visibility based on login vs register mode."""
if _is_register_mode: if _is_register_mode:
@@ -116,7 +109,7 @@ func _update_auth_mode_ui() -> void:
_dob_edit.visible = false _dob_edit.visible = false
# ── Auth submission ────────────────────────────────────────────────────────── # ─── Auth submission ──────────────────────────────────────────────────────────
func _on_auth_button_pressed() -> void: func _on_auth_button_pressed() -> void:
"""Handle login or register button press.""" """Handle login or register button press."""
@@ -173,12 +166,16 @@ func _on_auth_complete(result: Dictionary) -> void:
_is_authenticating = false _is_authenticating = false
if result.ok: if result.ok:
# Success — show welcome, enable Play, hide the now-redundant # Success — hide the auth form fields, show only the welcome label.
# Login/Register entry points (the auth panel itself stays open, _username_edit.visible = false
# showing the welcome message in place of the form). _password_edit.visible = false
_email_edit.visible = false
_dob_edit.visible = false
_auth_button.visible = false
_auth_mode_label.visible = false
_status_label.visible = false
_welcome_label.text = "Welcome, %s!" % _username_edit.text.strip_edges() _welcome_label.text = "Welcome, %s!" % _username_edit.text.strip_edges()
_welcome_label.visible = true _welcome_label.visible = true
_status_label.visible = false
_play_button.disabled = false _play_button.disabled = false
_auth_buttons_row.visible = false _auth_buttons_row.visible = false
print("Auth successful. Token stored.") print("Auth successful. Token stored.")
@@ -187,7 +184,7 @@ func _on_auth_complete(result: Dictionary) -> void:
_show_status(result.detail) _show_status(result.detail)
# ── Status helpers ─────────────────────────────────────────────────────────── # ─── Status helpers ───────────────────────────────────────────────────────────
func _show_status(message: String) -> void: func _show_status(message: String) -> void:
_status_label.text = message _status_label.text = message
@@ -199,7 +196,7 @@ func _clear_status() -> void:
_status_label.visible = false _status_label.visible = false
# ── Validation ─────────────────────────────────────────────────────────────── # ─── Validation ───────────────────────────────────────────────────────────────
func _is_valid_date(date_str: String) -> bool: func _is_valid_date(date_str: String) -> bool:
"""Check if a string looks like a valid YYYY-MM-DD date.""" """Check if a string looks like a valid YYYY-MM-DD date."""
+13 -3
View File
@@ -1,9 +1,8 @@
extends SceneTree extends SceneTree
## Full click-through simulation of the real user flow: press Register, ## Full click-through simulation of the real user flow: press Register,
## fill the form exactly as a human would, submit, confirm Play actually ## fill the form exactly as a human would, submit, confirm Play actually
## becomes clickable. This is the check that would have caught the ## becomes clickable. Also verifies that after successful auth the auth
## original bug (no way to even open the form) and would catch a repeat ## form fields are hidden, leaving only the welcome message visible.
## of it.
var passed := 0 var passed := 0
var failed := 0 var failed := 0
@@ -28,6 +27,7 @@ func _run() -> void:
var email_edit: LineEdit = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/EmailEdit") var email_edit: LineEdit = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/EmailEdit")
var dob_edit: LineEdit = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/DOBEdit") var dob_edit: LineEdit = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/DOBEdit")
var auth_button: Button = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/AuthButton") var auth_button: Button = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/AuthButton")
var auth_mode_label: Label = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/AuthModeLabel")
var welcome_label: Label = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/WelcomeLabel") var welcome_label: Label = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/WelcomeLabel")
var play_button: Button = instance.get_node("CenterContainer/VBoxContainer/PlayButton") var play_button: Button = instance.get_node("CenterContainer/VBoxContainer/PlayButton")
@@ -63,6 +63,16 @@ func _run() -> void:
_check("Welcome label visible", welcome_label.visible) _check("Welcome label visible", welcome_label.visible)
_check("Auth buttons row hid itself after success", not auth_buttons_row.visible) _check("Auth buttons row hid itself after success", not auth_buttons_row.visible)
# Verify the auth form fields are hidden after successful auth,
# leaving only the welcome message visible within the panel.
_check("Username edit hidden after auth", not username_edit.visible)
_check("Password edit hidden after auth", not password_edit.visible)
_check("Email edit hidden after auth", not email_edit.visible)
_check("DOB edit hidden after auth", not dob_edit.visible)
_check("Auth button hidden after auth", not auth_button.visible)
_check("Auth mode label hidden after auth", not auth_mode_label.visible)
_check("Welcome label contains username", welcome_label.text.begins_with("Welcome, mainmenu_e2e_"))
print("\n=== SMOKE RESULT: %d/%d passed ===" % [passed, passed + failed]) print("\n=== SMOKE RESULT: %d/%d passed ===" % [passed, passed + failed])
quit(0 if failed == 0 else 1) quit(0 if failed == 0 else 1)
+75 -9
View File
@@ -1,9 +1,14 @@
extends SceneTree extends SceneTree
## Verifies the main menu's Login/Register buttons actually open the auth ## Verifies the main menu's Login/Register buttons correctly open the auth
## panel via a real signal emission (not calling the handler method ## panel and toggle between Login and Register modes via signal emission.
## directly) -- that's the exact gap that shipped without ever being ##
## caught: the AuthPanel and its logic were all correct, but nothing in ## Key tests:
## the scene was ever wired to open it. ## - AuthPanel starts hidden.
## - LoginButton press opens the panel in Login mode.
## - RegisterButton press opens the panel in Register mode.
## - Clicking Login while in Register mode switches back to Login mode.
## - Clicking Register while in Login mode switches to Register mode.
## - The ModeToggle CheckButton no longer exists in the scene.
func _initialize() -> void: func _initialize() -> void:
@@ -24,26 +29,87 @@ func _run() -> void:
var login_button: Button = instance.get_node("CenterContainer/VBoxContainer/AuthButtonsRow/LoginButton") var login_button: Button = instance.get_node("CenterContainer/VBoxContainer/AuthButtonsRow/LoginButton")
var register_button: Button = instance.get_node("CenterContainer/VBoxContainer/AuthButtonsRow/RegisterButton") var register_button: Button = instance.get_node("CenterContainer/VBoxContainer/AuthButtonsRow/RegisterButton")
var auth_panel: PanelContainer = instance.get_node("CenterContainer/VBoxContainer/AuthPanel") var auth_panel: PanelContainer = instance.get_node("CenterContainer/VBoxContainer/AuthPanel")
var auth_mode_label: Label = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/AuthModeLabel")
var email_edit: LineEdit = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/EmailEdit")
var dob_edit: LineEdit = instance.get_node("CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/DOBEdit")
# --- Test 1: auth panel starts hidden ---
if _check("auth panel starts hidden", not auth_panel.visible): if _check("auth panel starts hidden", not auth_panel.visible):
passed += 1 passed += 1
else: else:
failed += 1 failed += 1
# --- Test 2: LoginButton press opens panel in Login mode ---
login_button.pressed.emit() login_button.pressed.emit()
await process_frame await process_frame
if _check("auth panel visible after a real LoginButton press signal", auth_panel.visible): if _check("auth panel visible after LoginButton press", auth_panel.visible):
passed += 1 passed += 1
else: else:
failed += 1 failed += 1
# Reset and check RegisterButton independently too. if _check("Login mode label after LoginButton press", auth_mode_label.text == "Login"):
auth_panel.visible = false passed += 1
else:
failed += 1
if _check("Email field hidden in Login mode", not email_edit.visible):
passed += 1
else:
failed += 1
if _check("DOB field hidden in Login mode", not dob_edit.visible):
passed += 1
else:
failed += 1
# --- Test 3: RegisterButton press switches to Register mode ---
register_button.pressed.emit() register_button.pressed.emit()
await process_frame await process_frame
if _check("auth panel visible after a real RegisterButton press signal", auth_panel.visible): if _check("auth panel still visible after RegisterButton press", auth_panel.visible):
passed += 1
else:
failed += 1
if _check("Register mode label after RegisterButton press", auth_mode_label.text == "Register"):
passed += 1
else:
failed += 1
if _check("Email field visible in Register mode", email_edit.visible):
passed += 1
else:
failed += 1
if _check("DOB field visible in Register mode", dob_edit.visible):
passed += 1
else:
failed += 1
# --- Test 4: LoginButton press switches back to Login mode ---
login_button.pressed.emit()
await process_frame
if _check("Login mode label after second LoginButton press", auth_mode_label.text == "Login"):
passed += 1
else:
failed += 1
if _check("Email field hidden after switching back to Login", not email_edit.visible):
passed += 1
else:
failed += 1
if _check("DOB field hidden after switching back to Login", not dob_edit.visible):
passed += 1
else:
failed += 1
# --- Test 5: ModeToggle CheckButton no longer exists ---
var mode_toggle_path = "CenterContainer/VBoxContainer/AuthPanel/MarginContainer/AuthVBox/ModeToggle"
var has_mode_toggle = instance.has_node(mode_toggle_path)
if _check("ModeToggle CheckButton removed from scene", not has_mode_toggle):
passed += 1 passed += 1
else: else:
failed += 1 failed += 1