mirror of
https://github.com/rendercv/rendercv.git
synced 2025-12-23 21:47:55 -05:00
266 lines
9.5 KiB
Python
266 lines
9.5 KiB
Python
from typing import Any
|
|
|
|
import pytest
|
|
|
|
from rendercv.exception import RenderCVUserError
|
|
from rendercv.schema.override_dictionary import (
|
|
apply_overrides_to_dictionary,
|
|
update_value_by_location,
|
|
)
|
|
|
|
|
|
class TestUpdateValueByLocation:
|
|
@pytest.mark.parametrize(
|
|
("initial_dict", "key", "value", "expected"),
|
|
[
|
|
({"name": "John"}, "name", "Jane", {"name": "Jane"}),
|
|
({"age": 30}, "age", "25", {"age": "25"}),
|
|
({}, "new_key", "new_value", {"new_key": "new_value"}),
|
|
],
|
|
)
|
|
def test_simple_dictionary_updates(self, initial_dict, key, value, expected):
|
|
result = update_value_by_location(initial_dict, key, value, key)
|
|
assert result == expected
|
|
|
|
@pytest.mark.parametrize(
|
|
("initial_dict", "key", "value", "expected"),
|
|
[
|
|
(
|
|
{"user": {"name": "John"}},
|
|
"user.name",
|
|
"Jane",
|
|
{"user": {"name": "Jane"}},
|
|
),
|
|
(
|
|
{"cv": {"sections": {"education": "MIT"}}},
|
|
"cv.sections.education",
|
|
"Harvard",
|
|
{"cv": {"sections": {"education": "Harvard"}}},
|
|
),
|
|
(
|
|
{"a": {"b": {"c": {"d": "old"}}}},
|
|
"a.b.c.d",
|
|
"new",
|
|
{"a": {"b": {"c": {"d": "new"}}}},
|
|
),
|
|
],
|
|
)
|
|
def test_nested_dictionary_updates(self, initial_dict, key, value, expected):
|
|
result = update_value_by_location(initial_dict, key, value, key)
|
|
assert result == expected
|
|
|
|
@pytest.mark.parametrize(
|
|
("initial_list", "key", "value", "expected"),
|
|
[
|
|
(["a", "b", "c"], "0", "x", ["x", "b", "c"]),
|
|
(["a", "b", "c"], "1", "y", ["a", "y", "c"]),
|
|
(["a", "b", "c"], "2", "z", ["a", "b", "z"]),
|
|
],
|
|
)
|
|
def test_list_updates(self, initial_list, key, value, expected):
|
|
result = update_value_by_location(initial_list, key, value, f"list.{key}")
|
|
assert result == expected
|
|
|
|
@pytest.mark.parametrize(
|
|
("initial_dict", "key", "value", "expected"),
|
|
[
|
|
(
|
|
{"items": ["a", "b", "c"]},
|
|
"items.1",
|
|
"updated",
|
|
{"items": ["a", "updated", "c"]},
|
|
),
|
|
(
|
|
{"cv": {"sections": ["edu", "exp"]}},
|
|
"cv.sections.0",
|
|
"education",
|
|
{"cv": {"sections": ["education", "exp"]}},
|
|
),
|
|
(
|
|
{"data": [{"name": "John"}, {"name": "Jane"}]},
|
|
"data.0.name",
|
|
"Bob",
|
|
{"data": [{"name": "Bob"}, {"name": "Jane"}]},
|
|
),
|
|
(
|
|
{"cv": {"sections": {"education": [{"institution": "MIT"}]}}},
|
|
"cv.sections.education.0.institution",
|
|
"Harvard",
|
|
{"cv": {"sections": {"education": [{"institution": "Harvard"}]}}},
|
|
),
|
|
],
|
|
)
|
|
def test_mixed_dict_list_traversal(self, initial_dict, key, value, expected):
|
|
result = update_value_by_location(initial_dict, key, value, key)
|
|
assert result == expected
|
|
|
|
@pytest.mark.parametrize(
|
|
("initial_dict", "key", "full_key"),
|
|
[
|
|
({"items": ["a", "b"]}, "items.invalid", "items.invalid"),
|
|
({"data": [1, 2, 3]}, "data.foo", "data.foo"),
|
|
],
|
|
)
|
|
def test_non_integer_index_for_list_raises_error(self, initial_dict, key, full_key):
|
|
with pytest.raises(
|
|
RenderCVUserError, match=r"corresponds to a list, but .* is not an integer"
|
|
):
|
|
update_value_by_location(initial_dict, key, "value", full_key)
|
|
|
|
@pytest.mark.parametrize(
|
|
("initial_dict", "key", "full_key"),
|
|
[
|
|
({"items": ["a", "b"]}, "items.5", "items.5"),
|
|
({"data": [1]}, "data.10", "data.10"),
|
|
],
|
|
)
|
|
def test_index_out_of_range_raises_error(self, initial_dict, key, full_key):
|
|
with pytest.raises(RenderCVUserError, match=r"Index .* is out of range"):
|
|
update_value_by_location(initial_dict, key, "value", full_key)
|
|
|
|
@pytest.mark.parametrize(
|
|
("initial_dict", "key", "full_key"),
|
|
[
|
|
({"name": "John"}, "name.field", "name.field"),
|
|
({"age": 30}, "age.value", "age.value"),
|
|
],
|
|
)
|
|
def test_invalid_structure_raises_error(self, initial_dict, key, full_key):
|
|
with pytest.raises(
|
|
RenderCVUserError, match="It seems like there's something wrong"
|
|
):
|
|
update_value_by_location(initial_dict, key, "value", full_key)
|
|
|
|
def test_mutates_original_structure(self):
|
|
original = {"name": "John"}
|
|
result = update_value_by_location(original, "name", "Jane", "name")
|
|
assert result is original
|
|
assert original == {"name": "Jane"}
|
|
|
|
def test_deeply_nested_structure(self):
|
|
initial: dict[str, Any] = {
|
|
"cv": {
|
|
"sections": {
|
|
"education": [
|
|
{
|
|
"institution": "MIT",
|
|
"degree": "PhD",
|
|
"details": {"gpa": "4.0"},
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
result = update_value_by_location(
|
|
initial,
|
|
"cv.sections.education.0.details.gpa",
|
|
"3.9",
|
|
"cv.sections.education.0.details.gpa",
|
|
)
|
|
assert result["cv"]["sections"]["education"][0]["details"]["gpa"] == "3.9"
|
|
|
|
|
|
class TestApplyOverridesToDictionary:
|
|
@pytest.mark.parametrize(
|
|
("initial_dict", "overrides", "expected"),
|
|
[
|
|
({"name": "John"}, {"name": "Jane"}, {"name": "Jane"}),
|
|
(
|
|
{"cv": {"name": "John"}},
|
|
{"cv.name": "Jane"},
|
|
{"cv": {"name": "Jane"}},
|
|
),
|
|
(
|
|
{"items": ["a", "b"]},
|
|
{"items.0": "x"},
|
|
{"items": ["x", "b"]},
|
|
),
|
|
],
|
|
)
|
|
def test_single_override(self, initial_dict, overrides, expected):
|
|
result = apply_overrides_to_dictionary(initial_dict, overrides)
|
|
assert result == expected
|
|
|
|
@pytest.mark.parametrize(
|
|
("initial_dict", "overrides", "expected"),
|
|
[
|
|
(
|
|
{"name": "John", "age": "30"},
|
|
{"name": "Jane", "age": "25"},
|
|
{"name": "Jane", "age": "25"},
|
|
),
|
|
(
|
|
{"cv": {"name": "John", "email": "john@example.com"}},
|
|
{"cv.name": "Jane", "cv.email": "jane@example.com"},
|
|
{"cv": {"name": "Jane", "email": "jane@example.com"}},
|
|
),
|
|
(
|
|
{"cv": {"sections": {"education": "MIT", "experience": "Google"}}},
|
|
{"cv.sections.education": "Harvard", "cv.sections.experience": "Meta"},
|
|
{"cv": {"sections": {"education": "Harvard", "experience": "Meta"}}},
|
|
),
|
|
],
|
|
)
|
|
def test_multiple_overrides(self, initial_dict, overrides, expected):
|
|
result = apply_overrides_to_dictionary(initial_dict, overrides)
|
|
assert result == expected
|
|
|
|
def test_does_not_mutate_original(self):
|
|
original = {"name": "John", "age": "30"}
|
|
original_copy = {"name": "John", "age": "30"}
|
|
overrides = {"name": "Jane"}
|
|
|
|
result = apply_overrides_to_dictionary(original, overrides)
|
|
|
|
assert original == original_copy # Original unchanged
|
|
assert result == {"name": "Jane", "age": "30"} # Result has override
|
|
assert result is not original # Different objects
|
|
|
|
def test_deep_copy_behavior(self):
|
|
original = {"cv": {"sections": {"education": ["MIT"]}}}
|
|
overrides = {"cv.sections.education.0": "Harvard"}
|
|
|
|
result = apply_overrides_to_dictionary(original, overrides)
|
|
|
|
assert original["cv"]["sections"]["education"][0] == "MIT"
|
|
assert result["cv"]["sections"]["education"][0] == "Harvard"
|
|
|
|
def test_empty_overrides(self):
|
|
original = {"name": "John", "age": "30"}
|
|
result = apply_overrides_to_dictionary(original, {})
|
|
assert result == original
|
|
assert result is not original
|
|
|
|
def test_complex_cv_scenario(self):
|
|
initial: dict[str, Any] = {
|
|
"cv": {
|
|
"name": "John Doe",
|
|
"sections": {
|
|
"education": [
|
|
{
|
|
"institution": "MIT",
|
|
"degree": "PhD",
|
|
"start_date": "2020-01",
|
|
}
|
|
],
|
|
"experience": [{"company": "Google", "title": "Engineer"}],
|
|
},
|
|
}
|
|
}
|
|
overrides = {
|
|
"cv.name": "Jane Doe",
|
|
"cv.sections.education.0.institution": "Harvard",
|
|
"cv.sections.education.0.start_date": "2021-01",
|
|
"cv.sections.experience.0.company": "Meta",
|
|
}
|
|
|
|
result = apply_overrides_to_dictionary(initial, overrides)
|
|
|
|
assert result["cv"]["name"] == "Jane Doe"
|
|
assert result["cv"]["sections"]["education"][0]["institution"] == "Harvard"
|
|
assert result["cv"]["sections"]["education"][0]["start_date"] == "2021-01"
|
|
assert result["cv"]["sections"]["education"][0]["degree"] == "PhD"
|
|
assert result["cv"]["sections"]["experience"][0]["company"] == "Meta"
|
|
assert result["cv"]["sections"]["experience"][0]["title"] == "Engineer"
|
|
assert initial["cv"]["name"] == "John Doe"
|