# Copyright: (c) 2025, Luca Bilke <luca@bil.ke> # MIT License (see LICENSE) from typing import Any from unittest import TestCase import pytest from ansible_collections.snailed.ez_compose.plugins.module_utils import common @pytest.mark.parametrize( ("test_input", "expected"), [ # pyright: ignore[reportUnknownArgumentType] # Basic nested update (using existing test variables) ( ( {"one": {"one": "keep", "two": "rewrite"}}, {"one": {"two": "new"}}, ), {"one": {"one": "keep", "two": "new"}}, ), # Deep nested update ( ( {"a": {"b": {"c": "old", "d": "keep"}}}, {"a": {"b": {"c": "new"}}}, ), {"a": {"b": {"c": "new", "d": "keep"}}}, ), # Adding new keys at different levels ( ( {"x": {"y": "original"}}, {"x": {"z": "new", "y": "updated"}, "new_key": "value"}, ), {"x": {"y": "updated", "z": "new"}, "new_key": "value"}, ), # Empty dict cases ( ( {}, {"new": "data"}, ), {"new": "data"}, ), ( ( {"existing": "data"}, {}, ), {"existing": "data"}, ), # Lists within dictionaries ( ( {"items": ["a", "b"], "nested": {"list": ["1", "2"]}}, {"items": ["c"], "nested": {"list": ["3"]}}, ), {"items": ["a", "b", "c"], "nested": {"list": ["1", "2", "3"]}}, ), # Lists of dictionaries ( ( { "configs": [ {"name": "config1", "value": "old"}, {"name": "config2", "enabled": True}, ], }, { "configs": [ {"name": "config3", "value": "new"}, {"name": "config4", "enabled": False}, ], }, ), { "configs": [ {"name": "config1", "value": "old"}, {"name": "config2", "enabled": True}, {"name": "config3", "value": "new"}, {"name": "config4", "enabled": False}, ], }, ), # Nested lists of dictionaries ( ( { "services": { "web": [ {"port": 80, "protocol": "http"}, {"port": 443, "protocol": "https"}, ], }, }, {"services": {"web": [{"port": 8080, "protocol": "http"}]}}, ), { "services": { "web": [ {"port": 80, "protocol": "http"}, {"port": 443, "protocol": "https"}, {"port": 8080, "protocol": "http"}, ], }, }, ), # Mixed types update ( ( {"mixed": {"num": 42, "list": [1, 2], "str": "old"}}, {"mixed": {"num": 43, "list": [3], "str": "new"}}, ), {"mixed": {"num": 43, "list": [1, 2, 3], "str": "new"}}, ), ], ) def test_recursive_update( test_input: tuple[dict[str, Any], dict[str, Any]], expected: dict[str, Any], ) -> None: TestCase().assertDictEqual(common.recursive_update(*test_input), expected)