extends "res://addons/gut/test.gd" const DmService = preload("res://scripts/net/dm_service.gd") const DmResponse = preload("res://scripts/net/dm_response.gd") const FallbackLibrary = preload("res://scripts/net/fallback_library.gd") const FakeDmTransport = preload("res://tests/doubles/fake_transport.gd") var _fallback func before_each(): # Point the library at a missing file so narrator_line() is deterministically # LAST_RESORT — the degraded assertions don't depend on the authored content. _fallback = FallbackLibrary.new("res://content/fallback/does_not_exist.json") func _log() -> CanonLog: return CanonLog.new() func _service_for(resp) -> Dictionary: var t = FakeDmTransport.new() t.set_response(resp) return {"svc": DmService.new(t, _fallback), "transport": t} func test_success_strips_tags_and_harvests_facts(): var body := {"prose": "The docks reek of tar. [FACT: the eastern bridge is out]"} var pair := _service_for(DmResponse.ok(200, body)) var r = await pair["svc"].narrate(_log()) assert_false(r.degraded) assert_eq(r.display_text, "The docks reek of tar.") assert_eq(r.facts, ["the eastern bridge is out"]) func test_success_posts_canon_log_to_narrate_path(): var pair := _service_for(DmResponse.ok(200, {"prose": "x"})) await pair["svc"].narrate(_log()) assert_eq(pair["transport"].last_path, "/dm/narrate") assert_true(pair["transport"].last_body.has("canon_log")) func test_502_degrades_to_fallback_with_no_facts(): var pair := _service_for(DmResponse.ok(502, {"detail": {"model_error": "boom"}})) var r = await pair["svc"].narrate(_log()) assert_true(r.degraded) assert_eq(r.display_text, FallbackLibrary.LAST_RESORT) assert_eq(r.facts, []) func test_422_degrades(): var pair := _service_for(DmResponse.ok(422, {"detail": {"canon_log_errors": ["x"]}})) var r = await pair["svc"].narrate(_log()) assert_true(r.degraded) func test_transport_failure_degrades(): var pair := _service_for(DmResponse.failed("connection refused")) var r = await pair["svc"].narrate(_log()) assert_true(r.degraded) func test_malformed_200_missing_prose_degrades(): var pair := _service_for(DmResponse.ok(200, {"nope": 1})) var r = await pair["svc"].narrate(_log()) assert_true(r.degraded) func test_malformed_200_non_dict_body_degrades(): var pair := _service_for(DmResponse.ok(200, null)) var r = await pair["svc"].narrate(_log()) assert_true(r.degraded) func test_only_facts_harvested_dispositions_and_moves_dropped(): var body := {"prose": "Hi [FACT: a] [ADJUST_DISPOSITION: +5] [MOVE: refuse()] bye"} var pair := _service_for(DmResponse.ok(200, body)) var r = await pair["svc"].narrate(_log()) assert_eq(r.facts, ["a"]) assert_eq(r.display_text, "Hi bye")