mirror of
https://github.com/rendercv/rendercv.git
synced 2026-04-22 15:59:45 -04:00
* Rename `data` folder with schema * Start refactoring data models * Work on entry models * Keep working on entries * Keep working on data models * Push old data files * Keep working on data models * First draft of schema.cv * Keep working on schema * Keep working on schema * Improve schema.models * Keep working on rendercv.schema * Work on schema.design * Keep working on rendercv.schema * Complete variant_class_generator * Keep working rendercv.schema * Keep working on rendercv.schema * Final touches to rendercv.schema * Improve json schema descriptions in rendercv.schema * Start working on rendercv.schema tests * Keep implementing rendercv.schema tests * Add more tests for rendercv.schema * Improve rendercv.schema * Improve docstrings and comments in rendercv.schema * Implement better pydantic error handling in `rendercv.schema` * Improve variant class system * Fix rendercv.schema tests * Start working on rendercv.templater * Update template names * Switching to new rendercv typst template soon * Work on new templater * Rename renderer with renderer_old * Don't use utils in rendercv.schema * Complete connections * Update renderer folder structure * Work on new renderer * Work on new renderer * Date processing on new renderer * Improve date processing, support multiple emails, phones, and websites * Improve markdown to Typst * Complete entry template processing * Time span computation in new renderer * Better entry templates * Setup new templates * Improve rendercv.schema * Start adding tests for rendercv.renderer * New markdown parser! * Improve markdown to typst conversion * Finalize markdown parser * Add new test files for rendercv.renderer * Fix cv and connections * Add connections test * Improve connection tests * Improve entry templates * Add model processor tests * Improve templater * Rename old folders * Improve schema * Add file generation logic to renderer * Fix naming issues * Fix schema tests * Add path type tests * Add font family and typst dimension type tests * Rename old tests * Fix design tests * Start integration testing of renderer * Improve entry tempates * Handle nested highlights properly * Finalize Typst preamble template * Start working on new CLI * Remove old test files * Implement override dictionary in new schema * Start working on new CLI * Better prints on render command * New structure * New render printer * Add all the commands to new CLI * Work on new command in new cli * Improve new command * Add error handler to new cli * Work on create theme command * Complete create theme command * Remove old source files * Improve exceptions * Create new docs * Add writing tests guide * Fix cli printer and write tests * Test copy templates * Add app tests * Bring back accidentally removed files * Imporve cli and tests * Fix path issues * Improve * Improve * Add reference file comparison tests * Fix path resolver * Start working on test_pdf_png * Implement comparison of multiple files (png) * Start testing typst * Fix templating issues * Fix header and entry templates issues * Implement short second rows * Fix date issues * Fix nested bullets and add summary * Update testdata * Implement footer * Update testdata * Reimagined design and locale schema, first iteration * Reimagined design and locale second iteration * Update design and locale schemas * Adapt templater to the new design and locale * Fix tests * Update lib.typ and testdata for the new locale and design * Implement proper tests with all combinations of entries * Remove some docstrings * fix connections logic * Improve * Start working on examples * Update testdata * Fix long second row issue * fix templating issues * Fix lib.typ issues * Update testdata * Fix clean_trailing_parts * Update test cv * update test cv * Update theme defaults * update schema and fix moderncv * Fix moderncv issues * Update testdata * Update testdata and examples * Fix issues about photo * Fix typst photo path issues * improve entry templates from yaml * add new locale * Rename writing tests doc * Update writing tests * Improve tests * Add more cli tests * Increase test coverage * Rename variant pydantic model generator * Improve tests * Update testdata and improve tests * Format, fix pre-commit errors * Fix scripts and update entry figures * Improve tests * Write docstrings of schema * Write schema docstrings * Setup api reference * Start working on new docs * Work on docs * Improve progress panel of render command * Finalize new docs index * Complete CLI docs * Work on YAML input structure page * Finalize user guide * Start working on developer guide * Improve api reference * Improve developer guide * Improve developer guide * Improve developer gide * Improve developer guide * Improve developer guide * Update developer guide * Improve developer guide * Improve developer guide * Improve developer guide * Developer guide first draft * update developer guide * Update examples * Update testdata * Handle wrong installation (rendercv instead of rendercv[full]) * Remove unnecessary files * Write set up vs code page * Update README.md * Change docs description * Compress design options gif * minor updates * Polish all the json schema descriptions * Update testdata and examples * Remove some emdashed from docs * Add whatsapp support * Add TestEscapeTypstCharacters to tests * Implement custom connections * Add page break before sections feature * Revert page break before sections feature * Rebase to main * Fix social network tests, update schema
179 lines
6.5 KiB
Python
179 lines
6.5 KiB
Python
from datetime import date as Date
|
||
|
||
import pydantic
|
||
import pytest
|
||
|
||
from rendercv.renderer.templater.model_processor import process_fields, process_model
|
||
from rendercv.schema.models.cv.cv import Cv
|
||
from rendercv.schema.models.cv.entries.normal import NormalEntry
|
||
from rendercv.schema.models.rendercv_model import RenderCVModel
|
||
|
||
|
||
@pytest.fixture
|
||
def recorder():
|
||
"""Return a processor function and a list tracking all values it has processed.
|
||
|
||
Used to verify which fields get processed and in what order.
|
||
"""
|
||
seen = []
|
||
|
||
def fn(v: str) -> str:
|
||
seen.append(v)
|
||
return f"processed-{v}"
|
||
|
||
return fn, seen
|
||
|
||
|
||
class TestProcessFields:
|
||
def test_applies_processors_in_order(self):
|
||
processors = [lambda s: s.upper(), lambda s: f"{s}!"]
|
||
result = process_fields("content", processors)
|
||
assert result == "CONTENT!"
|
||
|
||
def test_processes_fields_and_mutates_entry(self, recorder):
|
||
fn, seen = recorder
|
||
|
||
entry = NormalEntry.model_validate(
|
||
{
|
||
"name": "Entry",
|
||
"summary": "hello",
|
||
"highlights": ["a", "b"],
|
||
"start_date": "2020-01-01",
|
||
"end_date": "2020-02-01",
|
||
"location": "Remote",
|
||
}
|
||
)
|
||
|
||
process_fields(entry, [fn])
|
||
|
||
assert "hello" in seen
|
||
assert "a" in seen
|
||
assert "b" in seen
|
||
assert "Remote" in seen
|
||
|
||
assert "2020-01-01" not in seen
|
||
assert "2020-02-01" not in seen
|
||
assert entry.summary == "processed-hello"
|
||
assert entry.highlights == ["processed-a", "processed-b"]
|
||
assert entry.location == "processed-Remote"
|
||
|
||
assert entry.start_date == "2020-01-01"
|
||
assert entry.end_date == "2020-02-01"
|
||
|
||
def test_converts_non_string_non_list_fields_to_string(self, recorder):
|
||
class EntryWithInt(pydantic.BaseModel):
|
||
name: str
|
||
count: int
|
||
|
||
fn, seen = recorder
|
||
entry = EntryWithInt(name="Test", count=42)
|
||
|
||
process_fields(entry, [fn]) # pyright: ignore[reportArgumentType]
|
||
|
||
assert "Test" in seen
|
||
assert "42" in seen
|
||
assert entry.name == "processed-Test"
|
||
assert entry.count == "processed-42"
|
||
|
||
|
||
@pytest.fixture(params=[["Python", "Remote"], []])
|
||
def model(request: pytest.FixtureRequest) -> RenderCVModel:
|
||
"""Return a test RenderCVModel with keywords either set or empty.
|
||
|
||
Parametrized to test both with and without bold keywords.
|
||
"""
|
||
cv_data = {
|
||
# Order matters for connections
|
||
"name": "Jane Doe @",
|
||
"headline": "Software Engineer @",
|
||
"email": "jane@example.com",
|
||
"website": "https://janedoe.dev",
|
||
"sections": {
|
||
"Professional Experience": [
|
||
{
|
||
"name": "Backend Work",
|
||
"summary": "Built Python services with *markdown* emphasis.",
|
||
"highlights": ["Improved Python performance"],
|
||
"start_date": "2022-01-01",
|
||
"end_date": "2023-02-01",
|
||
"location": "Remote",
|
||
}
|
||
]
|
||
},
|
||
}
|
||
cv = Cv.model_validate(cv_data)
|
||
|
||
rendercv_model = RenderCVModel(cv=cv)
|
||
rendercv_model.settings.current_date = Date(2024, 2, 1)
|
||
rendercv_model.settings.bold_keywords = request.param
|
||
|
||
return rendercv_model
|
||
|
||
|
||
class TestProcessModel:
|
||
def test_markdown_output_has_correct_structure(self, model):
|
||
result = process_model(model, "markdown")
|
||
|
||
assert result.cv.name == "Jane Doe @"
|
||
assert result.cv.headline == "Software Engineer @"
|
||
|
||
# Connections and last updated date are added to cv
|
||
assert result.cv.connections == [ # pyright: ignore[reportAttributeAccessIssue]
|
||
"[jane@example.com](mailto:jane@example.com)",
|
||
"[janedoe.dev](https://janedoe.dev/)",
|
||
]
|
||
assert result.cv.top_note == "*Last updated in Feb 2024*" # pyright: ignore[reportAttributeAccessIssue]
|
||
|
||
entry = result.cv.rendercv_sections[0].entries[0]
|
||
assert entry.main_column.startswith("**Backend Work**")
|
||
if model.settings.bold_keywords:
|
||
assert (
|
||
"Built **Python** services with *markdown* emphasis."
|
||
in entry.main_column
|
||
)
|
||
assert "- Improved **Python** performance" in entry.main_column
|
||
# DATE placeholder removed because it's not provided; location remains
|
||
assert entry.date_and_location_column == "**Remote**\nJan 2022 – Feb 2023"
|
||
else:
|
||
assert (
|
||
"Built Python services with *markdown* emphasis." in entry.main_column
|
||
)
|
||
assert "- Improved Python performance" in entry.main_column
|
||
assert entry.date_and_location_column == "Remote\nJan 2022 – Feb 2023"
|
||
|
||
def test_typst_output_escapes_special_characters(self, model):
|
||
result = process_model(model, "typst")
|
||
|
||
assert result.cv.name == "Jane Doe \\@"
|
||
assert result.cv.headline == "Software Engineer \\@"
|
||
|
||
entry = result.cv.rendercv_sections[0].entries[0]
|
||
assert entry.main_column.startswith("#strong[Backend Work]")
|
||
if model.settings.bold_keywords:
|
||
assert "- Improved #strong[Python] performance" in entry.main_column
|
||
assert (
|
||
entry.date_and_location_column == "#strong[Remote]\nJan 2022 – Feb 2023"
|
||
)
|
||
# Connections rendered as Typst links with icons by default
|
||
assert result.cv.connections[0].startswith("#link(") # pyright: ignore[reportAttributeAccessIssue]
|
||
assert "#connection-with-icon" in result.cv.connections[0] # pyright: ignore[reportAttributeAccessIssue]
|
||
else:
|
||
assert "- Improved Python performance" in entry.main_column
|
||
assert entry.date_and_location_column == "Remote\nJan 2022 – Feb 2023"
|
||
assert result.cv.connections[0].startswith("#link(") # pyright: ignore[reportAttributeAccessIssue]
|
||
assert "jane@example.com" in result.cv.connections[0] # pyright: ignore[reportAttributeAccessIssue]
|
||
|
||
def test_handles_cv_with_no_sections(self):
|
||
cv_data = {
|
||
"name": "Jane Doe",
|
||
"headline": "Software Engineer",
|
||
}
|
||
cv = Cv.model_validate(cv_data)
|
||
rendercv_model = RenderCVModel(cv=cv)
|
||
|
||
result = process_model(rendercv_model, "markdown")
|
||
|
||
assert result.cv.name == "Jane Doe"
|
||
assert result.cv.headline == "Software Engineer"
|
||
assert hasattr(result.cv, "connections")
|