Files
settled-reach/client/tests/test_snapshot_event_router.gd
T
jpmschweitzerandClaude Opus 4.6 964bb9c459 refactor(client): extract SnapshotEventRouter from main.gd (#559)
New SnapshotEventRouter class (46 lines) provides callable-based
snapshot dispatch via register(), register_always(), and dispatch().
main.gd _process() now calls _router.dispatch(snapshot) instead of
15+ inline if-has blocks. Handlers registered in _ready().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:59:56 +01:00

90 lines
3.3 KiB
GDScript

## SnapshotEventRouter unit tests (#559).
## Verifies callable-based dispatch: keyed handlers receive correct field values,
## always handlers run on every dispatch, absent fields don't trigger handlers.
##
## D-030: fixture-based, server-free, no subprocess required.
class_name TestSnapshotEventRouter
extends GdUnitTestSuite
# -- Keyed handlers -----------------------------------------------------------
func test_keyed_handler_called_when_field_present() -> void:
var router := SnapshotEventRouter.new()
var received: Array = []
router.register("current_monologue", func(): received.append("monologue"))
router.dispatch({"current_monologue": {"text": "Test."}})
assert_that(received.size()).is_equal(1)
assert_that(received[0]).is_equal("monologue")
func test_keyed_handler_not_called_when_field_absent() -> void:
var router := SnapshotEventRouter.new()
var received: Array = []
router.register("current_monologue", func(): received.append("monologue"))
router.dispatch({"tick": 1})
assert_that(received.size()).is_equal(0)
func test_multiple_keyed_handlers_same_field() -> void:
## Multiple handlers on the same key run in registration order.
var router := SnapshotEventRouter.new()
var order: Array = []
router.register("save_result", func(): order.append("first"))
router.register("save_result", func(): order.append("second"))
router.dispatch({"save_result": {"success": true}})
assert_that(order).is_equal(["first", "second"])
func test_keyed_handlers_multiple_fields() -> void:
## Each keyed handler fires only for its registered field.
var router := SnapshotEventRouter.new()
var received: Array = []
router.register("current_monologue", func(): received.append("mono"))
router.register("current_dialogue", func(): received.append("dlg"))
router.dispatch({"current_monologue": {"text": "Hi."}})
assert_that(received).is_equal(["mono"])
received.clear()
router.dispatch({"current_dialogue": {"speech": "Hello."}, "current_monologue": {"text": "Hmm."}})
assert_bool(received.has("mono")).is_true()
assert_bool(received.has("dlg")).is_true()
# -- Always handlers ----------------------------------------------------------
func test_always_handler_called_on_every_dispatch() -> void:
var router := SnapshotEventRouter.new()
var count: Array[int] = [0]
router.register_always(func(): count[0] += 1)
router.dispatch({"tick": 1})
router.dispatch({"tick": 2})
router.dispatch({})
assert_int(count[0]).is_equal(3)
func test_always_handler_runs_before_keyed() -> void:
## Always handlers run before keyed handlers (dispatch order guarantee).
var router := SnapshotEventRouter.new()
var order: Array = []
router.register("current_monologue", func(): order.append("keyed"))
router.register_always(func(): order.append("always"))
router.dispatch({"current_monologue": {"text": "Hi."}})
assert_that(order[0]).is_equal("always")
assert_that(order[1]).is_equal("keyed")
# -- Empty dispatch ------------------------------------------------------------
func test_empty_snapshot_no_crash() -> void:
var router := SnapshotEventRouter.new()
router.register("foo", func(): pass)
router.register_always(func(): pass)
# Must not crash
router.dispatch({})
func test_no_handlers_no_crash() -> void:
var router := SnapshotEventRouter.new()
# Must not crash
router.dispatch({"tick": 1, "entities": []})