diff --git a/tests/test_language_override_lifecycle.py b/tests/test_language_override_lifecycle.py index 89cce0c70..f75ea53d4 100644 --- a/tests/test_language_override_lifecycle.py +++ b/tests/test_language_override_lifecycle.py @@ -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]) diff --git a/tests/test_oversized_document_slicing.py b/tests/test_oversized_document_slicing.py index e8ad54a6f..646956387 100644 --- a/tests/test_oversized_document_slicing.py +++ b/tests/test_oversized_document_slicing.py @@ -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.""" diff --git a/tests/test_yaml_extraction.py b/tests/test_yaml_extraction.py new file mode 100644 index 000000000..e76375675 --- /dev/null +++ b/tests/test_yaml_extraction.py @@ -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"