extends SceneTree
## Gate: the room list's "Purge" button asks before it purges (hyper-games #93 §1).
##
## room.purge leaves the keet room (keet-daemon router.js _roomPurge →
## core.leaveRoom), so getting back in needs a new invite. The button used to
## call it on the first click, with no confirmation.
##
## The menu is taken out of game.tscn on its own (Game's _ready never runs),
## and KeetService.room_mgr is swapped for a stub that records purge calls, so
## no daemon is touched.
##
## Run with no daemon: HYPERTPS_DAEMON_TCP=127.0.0.1:1 makes KeetService's
## client fail to connect harmlessly instead of talking to whatever daemon
## happens to be on this machine.
const ROOM_ID := "gatepurgeroom0000000000000000000000000000000000000000"
const ROOM_TITLE := "Gate Purge Room"
var ok := true
var _ran := false
func _p(c: bool, m: String) -> void:
print(("ok " if c else "FAIL: ") + m)
if not c:
ok = false
func _process(_delta: float) -> bool:
if _ran:
return true
_ran = true
_run()
print("GATE purge_confirm: %s" % ("PASS" if ok else "FAIL"))
quit(0 if ok else 1)
return true
func _dialogs(menu: Node) -> Array[ConfirmationDialog]:
var out: Array[ConfirmationDialog] = []
for c in menu.get_children():
if c is ConfirmationDialog and not c.is_queued_for_deletion():
out.append(c)
return out
func _run() -> void:
var keet: Node = root.get_node_or_null("KeetService")
_p(keet != null, "KeetService autoload present")
if keet == null:
return
var stub := preload("res://scenes/test/_stub_keet_room_purge.gd").new()
var real_mgr: Node = keet.room_mgr
keet.room_mgr = stub
keet._room_cache[ROOM_ID] = ROOM_TITLE
var game_scene := load("res://scenes/game/game.tscn") as PackedScene
_p(game_scene != null, "game.tscn loads")
if game_scene == null:
return
var game: Node = game_scene.instantiate()
var menu: Node = game.get_node("MenuUI/MenuMain")
menu.get_parent().remove_child(menu)
game.free()
root.add_child(menu)
# 1. One click purges nothing; it opens a confirmation naming the room.
menu._on_purge_room(ROOM_ID)
_p(stub.purged.is_empty(), "a click alone does not purge (purged=%s)" % str(stub.purged))
var dialogs := _dialogs(menu)
_p(dialogs.size() == 1, "one confirmation dialog is open (got %d)" % dialogs.size())
if dialogs.size() != 1:
_cleanup(menu, keet, real_mgr, stub)
return
var dlg := dialogs[0]
_p(dlg.visible, "the dialog is visible")
_p(dlg.dialog_text.contains(ROOM_TITLE), "the dialog names the room (text=%s)" % dlg.dialog_text)
_p(dlg.dialog_text.contains("invite"), "the dialog says rejoining needs an invite")
# 2. Cancel: nothing is purged and the dialog goes away.
dlg.canceled.emit()
_p(stub.purged.is_empty(), "cancel does not purge (purged=%s)" % str(stub.purged))
_p(_dialogs(menu).is_empty(), "cancel closes the dialog")
# 3. Confirm: exactly this room is purged, once.
menu._on_purge_room(ROOM_ID)
dialogs = _dialogs(menu)
_p(dialogs.size() == 1, "a second click opens a fresh dialog (got %d)" % dialogs.size())
if dialogs.size() == 1:
dialogs[0].confirmed.emit()
_p(stub.purged.size() == 1 and stub.purged[0] == ROOM_ID, "confirm purges this room once (purged=%s)" % str(stub.purged))
_p(_dialogs(menu).is_empty(), "confirm closes the dialog")
_cleanup(menu, keet, real_mgr, stub)
func _cleanup(menu: Node, keet: Node, real_mgr: Node, stub: Node) -> void:
keet.room_mgr = real_mgr
keet._room_cache.erase(ROOM_ID)
menu.queue_free()
stub.free()