test(yaml): add structural extraction coverage and update document tests (#2214)

- Add tests/test_yaml_extraction.py (classification, key nodes, contains edges,
  stable ids, scalar/empty documents).
- Drop .yaml/.yml from the oversized-document slicing parametrization: they are
  code now, not documents sent to the semantic pass.
- Point the language-override lifecycle test at .md so it still exercises a
  document override (yaml is no longer a document).
This commit is contained in:
nothariharan committed 2026-10-23 17:01:00 +05:30
1 parent 2e5565a684
commit b69b32e2f1
3 files changed
+66 -3

No files matched your search

+2 -2
View File
@@ -186,11 +186,11 @@ def test_watch_declared_code_updates_graph_on_observer_thread(tmp_path, monkeypa
def test_watch_document_override_marks_semantic_work_instead_of_rebuilding(tmp_path, monkeypatch):
events = pytest.importorskip("watchdog.events")
(tmp_path / ".graphifyrc").write_text("language.tpl=yaml\n")
(tmp_path / ".graphifyrc").write_text("language.tpl=md\n")
source = tmp_path / "notes.tpl"
def change():
source.write_text("service: database\n")
source.write_text("# notes\n\nservice: database\n")
return events.FileModifiedEvent(str(source))
drive_watch(tmp_path, monkeypatch, [change])
+1 -1
View File
@@ -104,7 +104,7 @@ def test_slices_stay_within_the_cap(tmp_path):
# End to end through the prompt builder
# ---------------------------------------------------------------------------
@pytest.mark.parametrize("ext", [".qmd", ".html", ".yaml", ".yml", ".skill"])
@pytest.mark.parametrize("ext", [".qmd", ".html", ".skill"])
def test_the_tail_of_a_big_document_reaches_the_prompt(tmp_path, ext):
"""The symptom a user would notice: content past 20k was invisible to the
semantic pass, so nothing in the tail could ever become a node."""
+63
View File
@@ -0,0 +1,63 @@
"""Structural YAML extraction (#2214).
YAML was previously classified as a document, so AST-only / code-only runs
(``graphify update``) produced zero nodes from config-heavy repositories
(Helm charts, Kubernetes manifests, CI pipelines). These tests pin the new
structural path: ``.yaml``/``.yml`` classify as code and ``extract_yaml``
emits deterministic file/key nodes.
"""
from __future__ import annotations
from pathlib import Path
from graphify.detect import FileType, classify_file
from graphify.extractors.yaml_config import extract_yaml
def _write(path: Path, text: str) -> Path:
path.write_text(text, encoding="utf-8")
return path
def test_yaml_and_yml_classify_as_code(tmp_path):
assert classify_file(_write(tmp_path / "values.yaml", "a: 1\n")) is FileType.CODE
assert classify_file(_write(tmp_path / "deploy.yml", "a: 1\n")) is FileType.CODE
def test_extract_yaml_top_level_keys(tmp_path):
path = _write(
tmp_path / "values.yaml",
"replicaCount: 2\nimage:\n tag: latest\nservice:\n port: 80\n",
)
result = extract_yaml(path)
assert "error" not in result
labels = {n["label"] for n in result["nodes"]}
assert {"values.yaml", "replicaCount", "image", "service"} <= labels
def test_extract_yaml_nested_keys_are_contains_edges(tmp_path):
path = _write(tmp_path / "values.yaml", "image:\n tag: latest\n pullPolicy: Always\n")
result = extract_yaml(path)
contains = [(e["source"], e["target"]) for e in result["edges"] if e["relation"] == "contains"]
assert any("image" in source and "tag" in target for source, target in contains)
assert any("image" in source and "pullpolicy" in target for source, target in contains)
def test_extract_yaml_ids_are_stable_across_runs(tmp_path):
path = _write(tmp_path / "values.yaml", "a: 1\nb:\n c: 2\n")
first = extract_yaml(path)
second = extract_yaml(path)
assert [n["id"] for n in first["nodes"]] == [n["id"] for n in second["nodes"]]
def test_extract_yaml_scalar_document_is_skipped(tmp_path):
result = extract_yaml(_write(tmp_path / "scalar.yaml", "just-a-string\n"))
assert result.get("skipped") == "scalar yaml"
def test_extract_yaml_empty_document(tmp_path):
result = extract_yaml(_write(tmp_path / "empty.yaml", ""))
assert result.get("skipped") == "scalar yaml"