Allow parameterizing YAML config in tests (#87981)
* Add fixture to parameterize yaml config * Apply to more tests * Re-add @fixture label * Add fixtures to patch yaml content and targets * Typo * Improve docstr Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Update references to mock_yaml_configuration * Apply new fixtures * Apply to check_config tests * Follow up comments * Rename fixtures, update docstr * Split paths * Patch load_yaml_config_file instead * sort * Fix tests * improve docst * Rename fixtures * sorting Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Improve docstr Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Improve docstr Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Improve docstr Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Improve docstr Co-authored-by: Erik Montnemery <erik@montnemery.com> * Improve docstr Co-authored-by: Erik Montnemery <erik@montnemery.com> * Improve docstr Co-authored-by: Erik Montnemery <erik@montnemery.com> --------- Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import importlib
|
||||
import io
|
||||
import os
|
||||
import pathlib
|
||||
from typing import Any
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
@@ -67,17 +68,17 @@ def test_simple_dict(try_both_loaders):
|
||||
assert doc["key"] == "value"
|
||||
|
||||
|
||||
def test_unhashable_key() -> None:
|
||||
@pytest.mark.parametrize("hass_config_yaml", ["message:\n {{ states.state }}"])
|
||||
def test_unhashable_key(mock_hass_config_yaml: None) -> None:
|
||||
"""Test an unhashable key."""
|
||||
files = {YAML_CONFIG_FILE: "message:\n {{ states.state }}"}
|
||||
with pytest.raises(HomeAssistantError), patch_yaml_files(files):
|
||||
with pytest.raises(HomeAssistantError):
|
||||
load_yaml_config_file(YAML_CONFIG_FILE)
|
||||
|
||||
|
||||
def test_no_key(try_both_loaders):
|
||||
@pytest.mark.parametrize("hass_config_yaml", ["a: a\nnokeyhere"])
|
||||
def test_no_key(try_both_loaders, mock_hass_config_yaml: None) -> None:
|
||||
"""Test item without a key."""
|
||||
files = {YAML_CONFIG_FILE: "a: a\nnokeyhere"}
|
||||
with pytest.raises(HomeAssistantError), patch_yaml_files(files):
|
||||
with pytest.raises(HomeAssistantError):
|
||||
yaml.load_yaml(YAML_CONFIG_FILE)
|
||||
|
||||
|
||||
@@ -106,35 +107,50 @@ def test_invalid_environment_variable(try_both_loaders):
|
||||
yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
|
||||
|
||||
def test_include_yaml(try_both_loaders):
|
||||
@pytest.mark.parametrize(
|
||||
("hass_config_yaml_files", "value"),
|
||||
[({"test.yaml": "value"}, "value"), ({"test.yaml": None}, {})],
|
||||
)
|
||||
def test_include_yaml(
|
||||
try_both_loaders, mock_hass_config_yaml: None, value: Any
|
||||
) -> None:
|
||||
"""Test include yaml."""
|
||||
with patch_yaml_files({"test.yaml": "value"}):
|
||||
conf = "key: !include test.yaml"
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert doc["key"] == "value"
|
||||
|
||||
with patch_yaml_files({"test.yaml": None}):
|
||||
conf = "key: !include test.yaml"
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert doc["key"] == {}
|
||||
conf = "key: !include test.yaml"
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert doc["key"] == value
|
||||
|
||||
|
||||
@patch("homeassistant.util.yaml.loader.os.walk")
|
||||
def test_include_dir_list(mock_walk, try_both_loaders):
|
||||
@pytest.mark.parametrize(
|
||||
"hass_config_yaml_files", [{"/test/one.yaml": "one", "/test/two.yaml": "two"}]
|
||||
)
|
||||
def test_include_dir_list(
|
||||
mock_walk, try_both_loaders, mock_hass_config_yaml: None
|
||||
) -> None:
|
||||
"""Test include dir list yaml."""
|
||||
mock_walk.return_value = [["/test", [], ["two.yaml", "one.yaml"]]]
|
||||
|
||||
with patch_yaml_files({"/test/one.yaml": "one", "/test/two.yaml": "two"}):
|
||||
conf = "key: !include_dir_list /test"
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert doc["key"] == sorted(["one", "two"])
|
||||
conf = "key: !include_dir_list /test"
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert doc["key"] == sorted(["one", "two"])
|
||||
|
||||
|
||||
@patch("homeassistant.util.yaml.loader.os.walk")
|
||||
def test_include_dir_list_recursive(mock_walk, try_both_loaders):
|
||||
@pytest.mark.parametrize(
|
||||
"hass_config_yaml_files",
|
||||
[
|
||||
{
|
||||
"/test/zero.yaml": "zero",
|
||||
"/test/tmp2/one.yaml": "one",
|
||||
"/test/tmp2/two.yaml": "two",
|
||||
}
|
||||
],
|
||||
)
|
||||
def test_include_dir_list_recursive(
|
||||
mock_walk, try_both_loaders, mock_hass_config_yaml: None
|
||||
) -> None:
|
||||
"""Test include dir recursive list yaml."""
|
||||
mock_walk.return_value = [
|
||||
["/test", ["tmp2", ".ignore", "ignore"], ["zero.yaml"]],
|
||||
@@ -142,41 +158,49 @@ def test_include_dir_list_recursive(mock_walk, try_both_loaders):
|
||||
["/test/ignore", [], [".ignore.yaml"]],
|
||||
]
|
||||
|
||||
with patch_yaml_files(
|
||||
{
|
||||
"/test/zero.yaml": "zero",
|
||||
"/test/tmp2/one.yaml": "one",
|
||||
"/test/tmp2/two.yaml": "two",
|
||||
}
|
||||
):
|
||||
conf = "key: !include_dir_list /test"
|
||||
with io.StringIO(conf) as file:
|
||||
assert (
|
||||
".ignore" in mock_walk.return_value[0][1]
|
||||
), "Expecting .ignore in here"
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert "tmp2" in mock_walk.return_value[0][1]
|
||||
assert ".ignore" not in mock_walk.return_value[0][1]
|
||||
assert sorted(doc["key"]) == sorted(["zero", "one", "two"])
|
||||
conf = "key: !include_dir_list /test"
|
||||
with io.StringIO(conf) as file:
|
||||
assert ".ignore" in mock_walk.return_value[0][1], "Expecting .ignore in here"
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert "tmp2" in mock_walk.return_value[0][1]
|
||||
assert ".ignore" not in mock_walk.return_value[0][1]
|
||||
assert sorted(doc["key"]) == sorted(["zero", "one", "two"])
|
||||
|
||||
|
||||
@patch("homeassistant.util.yaml.loader.os.walk")
|
||||
def test_include_dir_named(mock_walk, try_both_loaders):
|
||||
@pytest.mark.parametrize(
|
||||
"hass_config_yaml_files",
|
||||
[{"/test/first.yaml": "one", "/test/second.yaml": "two"}],
|
||||
)
|
||||
def test_include_dir_named(
|
||||
mock_walk, try_both_loaders, mock_hass_config_yaml: None
|
||||
) -> None:
|
||||
"""Test include dir named yaml."""
|
||||
mock_walk.return_value = [
|
||||
["/test", [], ["first.yaml", "second.yaml", "secrets.yaml"]]
|
||||
]
|
||||
|
||||
with patch_yaml_files({"/test/first.yaml": "one", "/test/second.yaml": "two"}):
|
||||
conf = "key: !include_dir_named /test"
|
||||
correct = {"first": "one", "second": "two"}
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert doc["key"] == correct
|
||||
conf = "key: !include_dir_named /test"
|
||||
correct = {"first": "one", "second": "two"}
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert doc["key"] == correct
|
||||
|
||||
|
||||
@patch("homeassistant.util.yaml.loader.os.walk")
|
||||
def test_include_dir_named_recursive(mock_walk, try_both_loaders):
|
||||
@pytest.mark.parametrize(
|
||||
"hass_config_yaml_files",
|
||||
[
|
||||
{
|
||||
"/test/first.yaml": "one",
|
||||
"/test/tmp2/second.yaml": "two",
|
||||
"/test/tmp2/third.yaml": "three",
|
||||
}
|
||||
],
|
||||
)
|
||||
def test_include_dir_named_recursive(
|
||||
mock_walk, try_both_loaders, mock_hass_config_yaml: None
|
||||
) -> None:
|
||||
"""Test include dir named yaml."""
|
||||
mock_walk.return_value = [
|
||||
["/test", ["tmp2", ".ignore", "ignore"], ["first.yaml"]],
|
||||
@@ -184,85 +208,99 @@ def test_include_dir_named_recursive(mock_walk, try_both_loaders):
|
||||
["/test/ignore", [], [".ignore.yaml"]],
|
||||
]
|
||||
|
||||
with patch_yaml_files(
|
||||
{
|
||||
"/test/first.yaml": "one",
|
||||
"/test/tmp2/second.yaml": "two",
|
||||
"/test/tmp2/third.yaml": "three",
|
||||
}
|
||||
):
|
||||
conf = "key: !include_dir_named /test"
|
||||
correct = {"first": "one", "second": "two", "third": "three"}
|
||||
with io.StringIO(conf) as file:
|
||||
assert (
|
||||
".ignore" in mock_walk.return_value[0][1]
|
||||
), "Expecting .ignore in here"
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert "tmp2" in mock_walk.return_value[0][1]
|
||||
assert ".ignore" not in mock_walk.return_value[0][1]
|
||||
assert doc["key"] == correct
|
||||
conf = "key: !include_dir_named /test"
|
||||
correct = {"first": "one", "second": "two", "third": "three"}
|
||||
with io.StringIO(conf) as file:
|
||||
assert ".ignore" in mock_walk.return_value[0][1], "Expecting .ignore in here"
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert "tmp2" in mock_walk.return_value[0][1]
|
||||
assert ".ignore" not in mock_walk.return_value[0][1]
|
||||
assert doc["key"] == correct
|
||||
|
||||
|
||||
@patch("homeassistant.util.yaml.loader.os.walk")
|
||||
def test_include_dir_merge_list(mock_walk, try_both_loaders):
|
||||
@pytest.mark.parametrize(
|
||||
"hass_config_yaml_files",
|
||||
[{"/test/first.yaml": "- one", "/test/second.yaml": "- two\n- three"}],
|
||||
)
|
||||
def test_include_dir_merge_list(
|
||||
mock_walk, try_both_loaders, mock_hass_config_yaml: None
|
||||
) -> None:
|
||||
"""Test include dir merge list yaml."""
|
||||
mock_walk.return_value = [["/test", [], ["first.yaml", "second.yaml"]]]
|
||||
|
||||
with patch_yaml_files(
|
||||
{"/test/first.yaml": "- one", "/test/second.yaml": "- two\n- three"}
|
||||
):
|
||||
conf = "key: !include_dir_merge_list /test"
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert sorted(doc["key"]) == sorted(["one", "two", "three"])
|
||||
conf = "key: !include_dir_merge_list /test"
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert sorted(doc["key"]) == sorted(["one", "two", "three"])
|
||||
|
||||
|
||||
@patch("homeassistant.util.yaml.loader.os.walk")
|
||||
def test_include_dir_merge_list_recursive(mock_walk, try_both_loaders):
|
||||
"""Test include dir merge list yaml."""
|
||||
mock_walk.return_value = [
|
||||
["/test", ["tmp2", ".ignore", "ignore"], ["first.yaml"]],
|
||||
["/test/tmp2", [], ["second.yaml", "third.yaml"]],
|
||||
["/test/ignore", [], [".ignore.yaml"]],
|
||||
]
|
||||
|
||||
with patch_yaml_files(
|
||||
@pytest.mark.parametrize(
|
||||
"hass_config_yaml_files",
|
||||
[
|
||||
{
|
||||
"/test/first.yaml": "- one",
|
||||
"/test/tmp2/second.yaml": "- two",
|
||||
"/test/tmp2/third.yaml": "- three\n- four",
|
||||
}
|
||||
):
|
||||
conf = "key: !include_dir_merge_list /test"
|
||||
with io.StringIO(conf) as file:
|
||||
assert (
|
||||
".ignore" in mock_walk.return_value[0][1]
|
||||
), "Expecting .ignore in here"
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert "tmp2" in mock_walk.return_value[0][1]
|
||||
assert ".ignore" not in mock_walk.return_value[0][1]
|
||||
assert sorted(doc["key"]) == sorted(["one", "two", "three", "four"])
|
||||
],
|
||||
)
|
||||
def test_include_dir_merge_list_recursive(
|
||||
mock_walk, try_both_loaders, mock_hass_config_yaml: None
|
||||
) -> None:
|
||||
"""Test include dir merge list yaml."""
|
||||
mock_walk.return_value = [
|
||||
["/test", ["tmp2", ".ignore", "ignore"], ["first.yaml"]],
|
||||
["/test/tmp2", [], ["second.yaml", "third.yaml"]],
|
||||
["/test/ignore", [], [".ignore.yaml"]],
|
||||
]
|
||||
|
||||
conf = "key: !include_dir_merge_list /test"
|
||||
with io.StringIO(conf) as file:
|
||||
assert ".ignore" in mock_walk.return_value[0][1], "Expecting .ignore in here"
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert "tmp2" in mock_walk.return_value[0][1]
|
||||
assert ".ignore" not in mock_walk.return_value[0][1]
|
||||
assert sorted(doc["key"]) == sorted(["one", "two", "three", "four"])
|
||||
|
||||
|
||||
@patch("homeassistant.util.yaml.loader.os.walk")
|
||||
def test_include_dir_merge_named(mock_walk, try_both_loaders):
|
||||
@pytest.mark.parametrize(
|
||||
"hass_config_yaml_files",
|
||||
[
|
||||
{
|
||||
"/test/first.yaml": "key1: one",
|
||||
"/test/second.yaml": "key2: two\nkey3: three",
|
||||
}
|
||||
],
|
||||
)
|
||||
def test_include_dir_merge_named(
|
||||
mock_walk, try_both_loaders, mock_hass_config_yaml: None
|
||||
) -> None:
|
||||
"""Test include dir merge named yaml."""
|
||||
mock_walk.return_value = [["/test", [], ["first.yaml", "second.yaml"]]]
|
||||
|
||||
files = {
|
||||
"/test/first.yaml": "key1: one",
|
||||
"/test/second.yaml": "key2: two\nkey3: three",
|
||||
}
|
||||
|
||||
with patch_yaml_files(files):
|
||||
conf = "key: !include_dir_merge_named /test"
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert doc["key"] == {"key1": "one", "key2": "two", "key3": "three"}
|
||||
conf = "key: !include_dir_merge_named /test"
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert doc["key"] == {"key1": "one", "key2": "two", "key3": "three"}
|
||||
|
||||
|
||||
@patch("homeassistant.util.yaml.loader.os.walk")
|
||||
def test_include_dir_merge_named_recursive(mock_walk, try_both_loaders):
|
||||
@pytest.mark.parametrize(
|
||||
"hass_config_yaml_files",
|
||||
[
|
||||
{
|
||||
"/test/first.yaml": "key1: one",
|
||||
"/test/tmp2/second.yaml": "key2: two",
|
||||
"/test/tmp2/third.yaml": "key3: three\nkey4: four",
|
||||
}
|
||||
],
|
||||
)
|
||||
def test_include_dir_merge_named_recursive(
|
||||
mock_walk, try_both_loaders, mock_hass_config_yaml: None
|
||||
) -> None:
|
||||
"""Test include dir merge named yaml."""
|
||||
mock_walk.return_value = [
|
||||
["/test", ["tmp2", ".ignore", "ignore"], ["first.yaml"]],
|
||||
@@ -270,27 +308,18 @@ def test_include_dir_merge_named_recursive(mock_walk, try_both_loaders):
|
||||
["/test/ignore", [], [".ignore.yaml"]],
|
||||
]
|
||||
|
||||
with patch_yaml_files(
|
||||
{
|
||||
"/test/first.yaml": "key1: one",
|
||||
"/test/tmp2/second.yaml": "key2: two",
|
||||
"/test/tmp2/third.yaml": "key3: three\nkey4: four",
|
||||
conf = "key: !include_dir_merge_named /test"
|
||||
with io.StringIO(conf) as file:
|
||||
assert ".ignore" in mock_walk.return_value[0][1], "Expecting .ignore in here"
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert "tmp2" in mock_walk.return_value[0][1]
|
||||
assert ".ignore" not in mock_walk.return_value[0][1]
|
||||
assert doc["key"] == {
|
||||
"key1": "one",
|
||||
"key2": "two",
|
||||
"key3": "three",
|
||||
"key4": "four",
|
||||
}
|
||||
):
|
||||
conf = "key: !include_dir_merge_named /test"
|
||||
with io.StringIO(conf) as file:
|
||||
assert (
|
||||
".ignore" in mock_walk.return_value[0][1]
|
||||
), "Expecting .ignore in here"
|
||||
doc = yaml_loader.yaml.load(file, Loader=yaml_loader.SafeLineLoader)
|
||||
assert "tmp2" in mock_walk.return_value[0][1]
|
||||
assert ".ignore" not in mock_walk.return_value[0][1]
|
||||
assert doc["key"] == {
|
||||
"key1": "one",
|
||||
"key2": "two",
|
||||
"key3": "three",
|
||||
"key4": "four",
|
||||
}
|
||||
|
||||
|
||||
@patch("homeassistant.util.yaml.loader.open", create=True)
|
||||
@@ -452,26 +481,31 @@ class TestSecrets(unittest.TestCase):
|
||||
)
|
||||
|
||||
|
||||
def test_representing_yaml_loaded_data(try_both_dumpers):
|
||||
@pytest.mark.parametrize("hass_config_yaml", ['key: [1, "2", 3]'])
|
||||
def test_representing_yaml_loaded_data(
|
||||
try_both_dumpers, mock_hass_config_yaml: None
|
||||
) -> None:
|
||||
"""Test we can represent YAML loaded data."""
|
||||
files = {YAML_CONFIG_FILE: 'key: [1, "2", 3]'}
|
||||
with patch_yaml_files(files):
|
||||
data = load_yaml_config_file(YAML_CONFIG_FILE)
|
||||
data = load_yaml_config_file(YAML_CONFIG_FILE)
|
||||
assert yaml.dump(data) == "key:\n- 1\n- '2'\n- 3\n"
|
||||
|
||||
|
||||
def test_duplicate_key(caplog, try_both_loaders):
|
||||
@pytest.mark.parametrize("hass_config_yaml", ["key: thing1\nkey: thing2"])
|
||||
def test_duplicate_key(caplog, try_both_loaders, mock_hass_config_yaml: None) -> None:
|
||||
"""Test duplicate dict keys."""
|
||||
files = {YAML_CONFIG_FILE: "key: thing1\nkey: thing2"}
|
||||
with patch_yaml_files(files):
|
||||
load_yaml_config_file(YAML_CONFIG_FILE)
|
||||
load_yaml_config_file(YAML_CONFIG_FILE)
|
||||
assert "contains duplicate key" in caplog.text
|
||||
|
||||
|
||||
def test_no_recursive_secrets(caplog, try_both_loaders):
|
||||
@pytest.mark.parametrize(
|
||||
"hass_config_yaml_files",
|
||||
[{YAML_CONFIG_FILE: "key: !secret a", yaml.SECRET_YAML: "a: 1\nb: !secret a"}],
|
||||
)
|
||||
def test_no_recursive_secrets(
|
||||
caplog, try_both_loaders, mock_hass_config_yaml: None
|
||||
) -> None:
|
||||
"""Test that loading of secrets from the secrets file fails correctly."""
|
||||
files = {YAML_CONFIG_FILE: "key: !secret a", yaml.SECRET_YAML: "a: 1\nb: !secret a"}
|
||||
with patch_yaml_files(files), pytest.raises(HomeAssistantError) as e:
|
||||
with pytest.raises(HomeAssistantError) as e:
|
||||
load_yaml_config_file(YAML_CONFIG_FILE)
|
||||
|
||||
assert e.value.args == ("Secrets not supported in this YAML file",)
|
||||
|
||||
Reference in New Issue
Block a user