Files
rendercv/tests/schema/models/test_path.py
2025-12-10 00:59:06 +03:00

231 lines
7.6 KiB
Python

import pathlib
import pydantic
import pytest
from rendercv.schema.models.path import (
ExistingPathRelativeToInput,
PlannedPathRelativeToInput,
)
from rendercv.schema.models.validation_context import ValidationContext
@pytest.fixture
def existing_file(tmp_path):
existing = tmp_path / "existing.txt"
existing.touch()
return existing
@pytest.fixture
def context_with_input_file(tmp_path):
return {"context": ValidationContext(input_file_path=tmp_path / "input.yaml")}
existing_input_relative_path_adapter = pydantic.TypeAdapter(ExistingPathRelativeToInput)
planned_input_relative_path_adapter = pydantic.TypeAdapter(PlannedPathRelativeToInput)
class TestExistingInputRelativePath:
def test_absolute_path_to_existing_file(
self, existing_file, context_with_input_file
):
result = existing_input_relative_path_adapter.validate_python(
existing_file, context=context_with_input_file
)
assert result == existing_file
def test_absolute_path_to_nonexistent_file_raises_error(
self, tmp_path, context_with_input_file
):
nonexistent = tmp_path / "nonexistent.txt"
with pytest.raises(pydantic.ValidationError, match="does not exist"):
existing_input_relative_path_adapter.validate_python(
nonexistent, context=context_with_input_file
)
def test_relative_path_to_existing_file(self, tmp_path, context_with_input_file):
existing = tmp_path / "relative_existing.txt"
existing.touch()
relative_path = pathlib.Path("relative_existing.txt")
result = existing_input_relative_path_adapter.validate_python(
relative_path, context=context_with_input_file
)
# Should be resolved relative to input_file_path directory
assert result == tmp_path / "relative_existing.txt"
assert result.exists()
def test_relative_path_to_nonexistent_file_raises_error(
self, context_with_input_file
):
relative_path = pathlib.Path("nonexistent_relative.txt")
with pytest.raises(pydantic.ValidationError, match="does not exist"):
existing_input_relative_path_adapter.validate_python(
relative_path, context=context_with_input_file
)
@pytest.mark.parametrize(
"relative_path",
[
pathlib.Path("subdir/file.txt"),
pathlib.Path("../sibling/file.txt"),
pathlib.Path("./same_dir/file.txt"),
],
)
def test_various_relative_path_formats(
self, tmp_path, context_with_input_file, relative_path
):
expected_path = tmp_path / relative_path
expected_path.parent.mkdir(parents=True, exist_ok=True)
expected_path.touch()
result = existing_input_relative_path_adapter.validate_python(
relative_path, context=context_with_input_file
)
assert result == expected_path
assert result.exists()
def test_path_string_validation(self, existing_file, context_with_input_file):
result = existing_input_relative_path_adapter.validate_python(
str(existing_file), context=context_with_input_file
)
assert result == existing_file
def test_existing_path_is_not_a_file_raises_error(
self, tmp_path, context_with_input_file
):
new_dir = tmp_path / "new_dir"
new_dir.mkdir()
with pytest.raises(pydantic.ValidationError, match="is not a file"):
existing_input_relative_path_adapter.validate_python(
new_dir, context=context_with_input_file
)
class TestPlannedInputRelativePath:
def test_absolute_path_to_existing_file(
self, existing_file, context_with_input_file
):
result = planned_input_relative_path_adapter.validate_python(
existing_file, context=context_with_input_file
)
assert result == existing_file
def test_absolute_path_to_nonexistent_file_is_accepted(
self, tmp_path, context_with_input_file
):
nonexistent = tmp_path / "planned_file.txt"
result = planned_input_relative_path_adapter.validate_python(
nonexistent, context=context_with_input_file
)
assert result == nonexistent
assert not result.exists()
def test_relative_path_to_existing_file(self, tmp_path, context_with_input_file):
existing = tmp_path / "relative_existing.txt"
existing.touch()
relative_path = pathlib.Path("relative_existing.txt")
result = planned_input_relative_path_adapter.validate_python(
relative_path, context=context_with_input_file
)
assert result == tmp_path / "relative_existing.txt"
assert result.exists()
def test_relative_path_to_nonexistent_file_is_accepted(
self, tmp_path, context_with_input_file
):
relative_path = pathlib.Path("planned_output.pdf")
result = planned_input_relative_path_adapter.validate_python(
relative_path, context=context_with_input_file
)
assert result == tmp_path / "planned_output.pdf"
assert not result.exists()
@pytest.mark.parametrize(
"relative_path",
[
pathlib.Path("output/result.pdf"),
pathlib.Path("../build/output.html"),
pathlib.Path("./generated/doc.md"),
],
)
def test_various_relative_path_formats_for_planned_paths(
self, tmp_path, context_with_input_file, relative_path
):
result = planned_input_relative_path_adapter.validate_python(
relative_path, context=context_with_input_file
)
expected_path = tmp_path / relative_path
assert result == expected_path
def test_path_string_validation(self, tmp_path, context_with_input_file):
planned_path = "output/generated.pdf"
result = planned_input_relative_path_adapter.validate_python(
planned_path, context=context_with_input_file
)
assert result == tmp_path / planned_path
class TestPathResolutionBehavior:
@pytest.mark.parametrize(
"path_adapter",
[existing_input_relative_path_adapter, planned_input_relative_path_adapter],
)
def test_absolute_path_remains_unchanged(
self, existing_file, context_with_input_file, path_adapter
):
result = path_adapter.validate_python(
existing_file, context=context_with_input_file
)
assert result == existing_file
assert result.is_absolute()
@pytest.mark.parametrize(
"path_adapter",
[existing_input_relative_path_adapter, planned_input_relative_path_adapter],
)
def test_relative_path_gets_resolved(
self, tmp_path, context_with_input_file, path_adapter
):
existing = tmp_path / "test.txt"
existing.touch()
relative_path = pathlib.Path("test.txt")
result = path_adapter.validate_python(
relative_path, context=context_with_input_file
)
assert result.is_absolute()
assert result == tmp_path / "test.txt"
def test_only_existing_type_validates_file_existence(
self, tmp_path, context_with_input_file
):
nonexistent_path = tmp_path / "does_not_exist.txt"
with pytest.raises(pydantic.ValidationError, match="does not exist"):
existing_input_relative_path_adapter.validate_python(
nonexistent_path, context=context_with_input_file
)
result = planned_input_relative_path_adapter.validate_python(
nonexistent_path, context=context_with_input_file
)
assert result == nonexistent_path