102 lines
2.9 KiB
Python
102 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
import textwrap
|
|
|
|
import yaml
|
|
|
|
from jinjaturtle.core import (
|
|
parse_config,
|
|
flatten_config,
|
|
generate_ansible_yaml,
|
|
generate_jinja2_template,
|
|
)
|
|
from jinjaturtle.handlers.yaml import YamlHandler
|
|
|
|
SAMPLES_DIR = Path(__file__).parent / "samples"
|
|
|
|
|
|
def test_yaml_roundtrip_with_list_and_comment():
|
|
yaml_path = SAMPLES_DIR / "bar.yaml"
|
|
assert yaml_path.is_file(), f"Missing sample YAML file: {yaml_path}"
|
|
|
|
fmt, parsed = parse_config(yaml_path)
|
|
assert fmt == "yaml"
|
|
|
|
flat_items = flatten_config(fmt, parsed)
|
|
ansible_yaml = generate_ansible_yaml("foobar", flat_items)
|
|
defaults = yaml.safe_load(ansible_yaml)
|
|
|
|
# Defaults: keys are flattened with indices
|
|
assert defaults["foobar_foo"] == "bar"
|
|
assert defaults["foobar_blah_0"] == "something"
|
|
assert defaults["foobar_blah_1"] == "else"
|
|
|
|
# Template generation (preserving comments)
|
|
original_text = yaml_path.read_text(encoding="utf-8")
|
|
template = generate_jinja2_template(
|
|
fmt, parsed, "foobar", original_text=original_text
|
|
)
|
|
|
|
# Comment preserved
|
|
assert "# Top comment" in template
|
|
|
|
# Scalar replacement
|
|
assert "foo:" in template
|
|
assert "foobar_foo" in template
|
|
|
|
# List items use indexed vars, not "item"
|
|
assert "foobar_blah_0" in template
|
|
assert "foobar_blah_1" in template
|
|
assert "{{ foobar_blah }}" not in template
|
|
assert "foobar_blah_item" not in template
|
|
|
|
|
|
def test_generate_yaml_template_from_text_edge_cases():
|
|
"""
|
|
Exercise YAML text edge cases:
|
|
- indentation dedent (stack pop)
|
|
- empty key before ':'
|
|
- quoted and unquoted list items
|
|
"""
|
|
text = textwrap.dedent(
|
|
"""
|
|
root:
|
|
child: 1
|
|
other: 2
|
|
: 3
|
|
list:
|
|
- "quoted"
|
|
- unquoted
|
|
"""
|
|
)
|
|
|
|
handler = YamlHandler()
|
|
tmpl = handler._generate_yaml_template_from_text("role", text)
|
|
|
|
# Dedent from "root -> child" back to "other" exercises the stack-pop path.
|
|
# Just check the expected variable names appear.
|
|
assert "role_root_child" in tmpl
|
|
assert "role_other" in tmpl
|
|
|
|
# The weird " : 3" line has no key and should be left untouched.
|
|
assert " : 3" in tmpl
|
|
|
|
# The list should generate indexed variables for each item.
|
|
# First item is quoted (use_quotes=True), second is unquoted.
|
|
assert "role_list_0" in tmpl
|
|
assert "role_list_1" in tmpl
|
|
|
|
|
|
def test_generate_jinja2_template_yaml_structural_fallback():
|
|
"""
|
|
When original_text is not provided for YAML, generate_jinja2_template should use
|
|
the structural fallback path (yaml.safe_dump + handler processing).
|
|
"""
|
|
parsed = {"outer": {"inner": "val"}}
|
|
|
|
tmpl = generate_jinja2_template("yaml", parsed=parsed, role_prefix="role")
|
|
|
|
# We don't care about exact formatting, just that the expected variable
|
|
# name shows up, proving we went through the structural path.
|
|
assert "role_outer_inner" in tmpl
|