OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / gate_purge_confirm.gd

102 lines · gd ref:
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()