Files
2026-07-13 13:08:41 +08:00

109 lines
3.2 KiB
Python

import pytest
from pydantic import TypeAdapter
from models.json_path_guide import DictGuide, JsonPathGuide, ListGuide
from utils.dict_utils import (
deep_update,
get_dict_at_path,
get_dict_paths_with_key,
has_more_than_n_keys,
set_dict_at_path,
)
def test_get_dict_paths_with_key_finds_nested_dict_and_list():
data = {
"a": {"props": {"x": 1}},
"b": [{"props": {"y": 2}}],
}
paths = get_dict_paths_with_key(data, "props")
assert len(paths) == 2
assert get_dict_at_path(data, paths[0]) == {"props": {"x": 1}}
assert get_dict_at_path(data, paths[1]) == {"props": {"y": 2}}
def test_set_dict_at_path_dict_and_list_final_keys():
one = {"level": {"final": 1}}
set_dict_at_path(
one,
JsonPathGuide(guides=[DictGuide(key="level"), DictGuide(key="final")]),
{"z": 9},
)
assert one["level"]["final"] == {"z": 9}
two = {"items": [{"n": 0}]}
set_dict_at_path(
two,
JsonPathGuide(guides=[DictGuide(key="items"), ListGuide(index=0)]),
{"n": 1},
)
assert two["items"][0] == {"n": 1}
three = {"rows": [{"a": 1}, {}]}
set_dict_at_path(
three,
JsonPathGuide(guides=[DictGuide(key="rows"), ListGuide(index=1)]),
{"patched": True},
)
assert three["rows"][1] == {"patched": True}
nested_lists = {"a": [[{}, {"reserved": False}]]}
set_dict_at_path(
nested_lists,
JsonPathGuide(
guides=[
DictGuide(key="a"),
ListGuide(index=0),
ListGuide(index=1),
]
),
{"filled": True},
)
assert nested_lists["a"][0][1] == {"filled": True}
def test_set_dict_at_path_empty_guides_is_noop():
data = {"a": 1}
set_dict_at_path(data, JsonPathGuide(guides=[]), {"x": 2})
assert data == {"a": 1}
def test_has_more_than_n_keys():
assert has_more_than_n_keys({"a": 1, "b": 2}, n=1) is True
assert has_more_than_n_keys({"a": 1}, n=1) is False
@pytest.mark.parametrize(
("original", "updates", "expected"),
[
({"a": {"x": 1}}, {"a": {"y": 2}}, {"a": {"x": 1, "y": 2}}),
({"a": [1, 2]}, {"a": []}, {"a": [1, 2]}),
({"a": [{"k": 1}]}, {"a": [{"k": 2}]}, {"a": [{"k": 2}]}),
({"a": [1, 2]}, {"a": [9, 8, 7]}, {"a": [9, 8]}),
({"a": 1}, {"a": 2}, {"a": 2}),
({}, {"b": 3}, {"b": 3}),
({"nested": {}}, {}, {"nested": {}}),
],
)
def test_deep_update_modes(original: dict, updates: dict, expected: dict):
assert deep_update(original, updates) == expected
def test_deep_update_deeply_nested_lists_of_dicts():
original = {"slides": [{"a": {"x": 1}}, {"b": 2}]}
updates = {"slides": [{"a": {"x": 2}}, {"b": 3}]}
assert deep_update(original, updates) == {"slides": [{"a": {"x": 2}}, {"b": 3}]}
def test_deep_update_single_dict_into_list_slot_with_scalar_original():
assert deep_update({"a": [99]}, {"a": [{"k": True}]}) == {"a": [{"k": True}]}
def test_json_path_guide_type_adapter_round_trip():
guide = JsonPathGuide(
guides=[DictGuide(key="x"), ListGuide(index=0), DictGuide(key="y")]
)
dumped = guide.model_dump()
restored = TypeAdapter(JsonPathGuide).validate_python(dumped)
assert restored == guide