## YamlParser unit tests (#560). ## Verifies parse() (nested, typed) and parse_flat() (dotted keys, string values). ## Covers: maps, nested maps, arrays of dicts, type conversion, comments, ## quoted strings, empty input, edge cases. ## ## D-030: fixture-based, server-free, no subprocess required. class_name TestYamlParser extends GdUnitTestSuite # -- parse(): basic key-value pairs ------------------------------------------- func test_parse_simple_key_value() -> void: var result := YamlParser.parse("key: value") assert_that(result["key"]).is_equal("value") func test_parse_quoted_string() -> void: var result := YamlParser.parse('key: "hello world"') assert_that(result["key"]).is_equal("hello world") func test_parse_empty_quoted_string() -> void: var result := YamlParser.parse('key: ""') assert_that(result["key"]).is_equal("") func test_parse_integer_value() -> void: var result := YamlParser.parse("count: 42") assert_that(result["count"]).is_equal(42) assert_that(typeof(result["count"])).is_equal(TYPE_INT) func test_parse_negative_integer() -> void: var result := YamlParser.parse("offset: -3") assert_that(result["offset"]).is_equal(-3) func test_parse_float_value() -> void: var result := YamlParser.parse("radius: 2.5") assert_that(typeof(result["radius"])).is_equal(TYPE_FLOAT) assert_float(result["radius"]).is_equal_approx(2.5, 0.001) func test_parse_boolean_true() -> void: var result := YamlParser.parse("enabled: true") assert_that(result["enabled"]).is_equal(true) assert_that(typeof(result["enabled"])).is_equal(TYPE_BOOL) func test_parse_boolean_false() -> void: var result := YamlParser.parse("enabled: false") assert_that(result["enabled"]).is_equal(false) func test_parse_empty_input() -> void: var result := YamlParser.parse("") assert_that(result.size()).is_equal(0) func test_parse_only_comments() -> void: var result := YamlParser.parse("# comment\n# another") assert_that(result.size()).is_equal(0) func test_parse_inline_comment_stripped() -> void: var result := YamlParser.parse("room_id: test # this is a comment") assert_that(result["room_id"]).is_equal("test") func test_parse_quoted_value_with_hash() -> void: ## Quoted strings preserve literal # characters. var result := YamlParser.parse('color: "#e0e8ff"') assert_that(result["color"]).is_equal("#e0e8ff") func test_parse_value_with_colon() -> void: var result := YamlParser.parse('time: "12:30"') assert_that(result["time"]).is_equal("12:30") # -- parse(): nested maps ----------------------------------------------------- func test_parse_nested_map() -> void: var yaml := "section:\n key: value" var result := YamlParser.parse(yaml) assert_that(result.has("section")).is_true() assert_that(result["section"] is Dictionary).is_true() assert_that(result["section"]["key"]).is_equal("value") func test_parse_deeply_nested() -> void: var yaml := "a:\n b:\n c: deep" var result := YamlParser.parse(yaml) assert_that(result["a"]["b"]["c"]).is_equal("deep") func test_parse_multiple_sections() -> void: var yaml := "hud:\n mode: Mode\ninteraction:\n talk: Talk" var result := YamlParser.parse(yaml) assert_that(result["hud"]["mode"]).is_equal("Mode") assert_that(result["interaction"]["talk"]).is_equal("Talk") func test_parse_multiple_keys_per_section() -> void: var yaml := "hud:\n a: 1\n b: 2\n c: 3" var result := YamlParser.parse(yaml) assert_that(result["hud"]["a"]).is_equal(1) assert_that(result["hud"]["b"]).is_equal(2) assert_that(result["hud"]["c"]).is_equal(3) func test_parse_sibling_subsections() -> void: var yaml := "states:\n a:\n x: 1\n b:\n x: 2" var result := YamlParser.parse(yaml) assert_that(result["states"]["a"]["x"]).is_equal(1) assert_that(result["states"]["b"]["x"]).is_equal(2) func test_parse_section_with_trailing_comment() -> void: ## "section: # comment" should be treated as a section header. var yaml := "section: # comment\n key: value" var result := YamlParser.parse(yaml) assert_that(result["section"]["key"]).is_equal("value") # -- parse(): arrays of dicts ------------------------------------------------- func test_parse_single_array_item() -> void: var yaml := "conditions:\n - id: test-1\n type: near\n x: 10" var result := YamlParser.parse(yaml) assert_that(result.has("conditions")).is_true() assert_that(result["conditions"] is Array).is_true() assert_that(result["conditions"].size()).is_equal(1) assert_that(result["conditions"][0]["id"]).is_equal("test-1") assert_that(result["conditions"][0]["type"]).is_equal("near") assert_that(result["conditions"][0]["x"]).is_equal(10) func test_parse_multiple_array_items() -> void: var yaml := "conditions:\n - id: a\n x: 1\n - id: b\n x: 2" var result := YamlParser.parse(yaml) assert_that(result["conditions"].size()).is_equal(2) assert_that(result["conditions"][0]["id"]).is_equal("a") assert_that(result["conditions"][1]["id"]).is_equal("b") func test_parse_array_items_with_blank_lines() -> void: var yaml := "conditions:\n - id: a\n x: 1\n\n - id: b\n x: 2" var result := YamlParser.parse(yaml) assert_that(result["conditions"].size()).is_equal(2) func test_parse_top_level_plus_array() -> void: ## Checklist format: top-level key-value pairs followed by a conditions array. var yaml := "room_id: warehouse\nconditions:\n - id: c1\n type: near\n x: 5" var result := YamlParser.parse(yaml) assert_that(result["room_id"]).is_equal("warehouse") assert_that(result["conditions"].size()).is_equal(1) assert_that(result["conditions"][0]["id"]).is_equal("c1") func test_parse_array_typed_values() -> void: var yaml := "items:\n - id: t\n x: 42\n radius: 2.5\n active: true" var result := YamlParser.parse(yaml) var item: Dictionary = result["items"][0] assert_that(item["x"]).is_equal(42) assert_that(typeof(item["radius"])).is_equal(TYPE_FLOAT) assert_that(item["active"]).is_equal(true) # -- parse_flat(): dotted keys ------------------------------------------------- func test_flat_simple() -> void: var yaml := "section:\n key: value" var result := YamlParser.parse_flat(yaml) assert_that(result.has("section.key")).is_true() assert_that(result["section.key"]).is_equal("value") func test_flat_deeply_nested() -> void: var yaml := "a:\n b:\n c: deep" var result := YamlParser.parse_flat(yaml) assert_that(result["a.b.c"]).is_equal("deep") func test_flat_multiple_sections() -> void: var yaml := "hud:\n mode: Mode\ninteraction:\n talk: Talk" var result := YamlParser.parse_flat(yaml) assert_that(result["hud.mode"]).is_equal("Mode") assert_that(result["interaction.talk"]).is_equal("Talk") func test_flat_values_are_strings() -> void: ## parse_flat returns all values as strings, unlike parse() which returns typed. var yaml := "section:\n count: 42\n rate: 0.9\n active: true" var result := YamlParser.parse_flat(yaml) assert_that(result["section.count"]).is_equal("42") assert_that(result["section.rate"]).is_equal("0.9") assert_that(result["section.active"]).is_equal("true") func test_flat_quoted_value() -> void: var yaml := 'section:\n key: "hello world"' var result := YamlParser.parse_flat(yaml) assert_that(result["section.key"]).is_equal("hello world") func test_flat_inline_comment() -> void: var yaml := "hud:\n mode: Standard # default" var result := YamlParser.parse_flat(yaml) assert_that(result["hud.mode"]).is_equal("Standard") func test_flat_empty_quoted_value() -> void: var yaml := 'hud:\n prefix: "" # No prefix' var result := YamlParser.parse_flat(yaml) assert_that(result.has("hud.prefix")).is_true() assert_that(result["hud.prefix"]).is_equal("") func test_flat_skips_arrays() -> void: ## Arrays have no dotted-key representation — they are skipped in flat output. var yaml := "room_id: test\nconditions:\n - id: c1\n x: 5" var result := YamlParser.parse_flat(yaml) assert_that(result.has("room_id")).is_true() # No dotted keys for array contents assert_that(result.has("conditions")).is_false() assert_that(result.has("conditions.0")).is_false() func test_flat_empty_input() -> void: var result := YamlParser.parse_flat("") assert_that(result.size()).is_equal(0) # -- Dialogue theme format (regression) ---------------------------------------- func test_dialogue_theme_format() -> void: ## dialogue-theme.yaml has top-level values and one nested map (npc_colors). var yaml := "player_color: \"#e0e8ff\"\nnpc_colors:\n 0: \"#4a9ebb\"\n 1: \"#6bc9a6\"\npassive_opacity: 0.9" var flat := YamlParser.parse_flat(yaml) assert_that(flat["player_color"]).is_equal("#e0e8ff") assert_that(flat["npc_colors.0"]).is_equal("#4a9ebb") assert_that(flat["npc_colors.1"]).is_equal("#6bc9a6") assert_that(flat["passive_opacity"]).is_equal("0.9") # -- Checklist format (regression) --------------------------------------------- func test_checklist_format() -> void: ## checklist.yaml: top-level kv + conditions array with typed values. var yaml := ("room_id: inventory_warehouse\nconditions:\n - id: test-1\n" + " condition_type: player_near\n x: 10\n y: 20\n radius: 3.0") var result := YamlParser.parse(yaml) assert_that(result["room_id"]).is_equal("inventory_warehouse") var cond: Dictionary = result["conditions"][0] assert_that(cond["id"]).is_equal("test-1") assert_that(cond["condition_type"]).is_equal("player_near") assert_that(cond["x"]).is_equal(10) assert_that(cond["y"]).is_equal(20) assert_that(typeof(cond["radius"])).is_equal(TYPE_FLOAT)