1+ import pytest
2+
13from cumulusci .cli .extra_yaml import resolve_extra_yaml
4+ from cumulusci .core .exceptions import CumulusCIUsageError
25
36
47def test_resolve_extra_yaml__none_when_no_input (monkeypatch ):
@@ -14,3 +17,73 @@ def test_resolve_extra_yaml__single_file(tmp_path, monkeypatch):
1417 assert result is not None
1518 assert "from file" in result
1619 assert result .startswith ("tasks:" )
20+
21+
22+ def test_resolve_extra_yaml__missing_file_raises (tmp_path , monkeypatch ):
23+ monkeypatch .delenv ("CUMULUSCI_EXTRA_YAML" , raising = False )
24+ with pytest .raises (CumulusCIUsageError , match = "not found" ):
25+ resolve_extra_yaml ((str (tmp_path / "does_not_exist.yml" ),))
26+
27+
28+ def test_resolve_extra_yaml__multiple_files_deep_merged (tmp_path , monkeypatch ):
29+ """Multiple files are deep-merged; last file wins on scalar conflicts."""
30+ import yaml
31+
32+ monkeypatch .delenv ("CUMULUSCI_EXTRA_YAML" , raising = False )
33+ a = tmp_path / "a.yml"
34+ a .write_text ("tasks:\n foo:\n description: from A\n group: alpha\n " )
35+ b = tmp_path / "b.yml"
36+ b .write_text ("tasks:\n foo:\n description: from B\n " )
37+ result = resolve_extra_yaml ((str (a ), str (b )))
38+ assert result is not None
39+ parsed = yaml .safe_load (result )
40+ # Later file's scalar wins.
41+ assert parsed ["tasks" ]["foo" ]["description" ] == "from B"
42+ # Sibling keys from earlier file are preserved (deep merge).
43+ assert parsed ["tasks" ]["foo" ]["group" ] == "alpha"
44+
45+
46+ def test_resolve_extra_yaml__env_var_fallback (tmp_path , monkeypatch ):
47+ p = tmp_path / "env.yml"
48+ p .write_text ("project:\n name: env-loaded\n " )
49+ monkeypatch .setenv ("CUMULUSCI_EXTRA_YAML" , str (p ))
50+ result = resolve_extra_yaml (())
51+ assert result is not None
52+ assert "env-loaded" in result
53+
54+
55+ def test_resolve_extra_yaml__env_var_multiple_colon_separated (tmp_path , monkeypatch ):
56+ """Env var with multiple paths produces a deep-merged document."""
57+ import yaml
58+
59+ a = tmp_path / "a.yml"
60+ a .write_text ("tasks:\n a:\n description: from A\n " )
61+ b = tmp_path / "b.yml"
62+ b .write_text ("tasks:\n b:\n description: from B\n " )
63+ monkeypatch .setenv ("CUMULUSCI_EXTRA_YAML" , f"{ a } :{ b } " )
64+ result = resolve_extra_yaml (())
65+ assert result is not None
66+ parsed = yaml .safe_load (result )
67+ assert parsed ["tasks" ]["a" ]["description" ] == "from A"
68+ assert parsed ["tasks" ]["b" ]["description" ] == "from B"
69+
70+
71+ def test_resolve_extra_yaml__flag_overrides_env_var (tmp_path , monkeypatch ):
72+ flag_file = tmp_path / "flag.yml"
73+ flag_file .write_text ("tasks:\n from: flag\n " )
74+ env_file = tmp_path / "env.yml"
75+ env_file .write_text ("tasks:\n from: env\n " )
76+ monkeypatch .setenv ("CUMULUSCI_EXTRA_YAML" , str (env_file ))
77+ result = resolve_extra_yaml ((str (flag_file ),))
78+ assert result is not None
79+ assert "from: flag" in result
80+ assert "from: env" not in result
81+
82+
83+ def test_resolve_extra_yaml__empty_env_var_segments_ignored (tmp_path , monkeypatch ):
84+ p = tmp_path / "x.yml"
85+ p .write_text ("project: {}\n " )
86+ monkeypatch .setenv ("CUMULUSCI_EXTRA_YAML" , f"::{ p } ::" )
87+ result = resolve_extra_yaml (())
88+ assert result is not None
89+ assert "project: {}" in result
0 commit comments