Files
rendercv/tests/cli/render_command/test_progress_panel.py
2026-02-17 18:42:08 +03:00

296 lines
9.4 KiB
Python

import pathlib
import pytest
import typer
from rendercv.cli.render_command.progress_panel import (
CompletedStep,
ProgressPanel,
format_validation_error_location,
)
from rendercv.exception import RenderCVUserError, RenderCVValidationError
class TestFormatValidationErrorLocation:
def test_returns_schema_location_when_available(self):
error = RenderCVValidationError(
schema_location=("cv", "email"),
yaml_location=((2, 3), (2, 8)),
yaml_source="main_yaml_file",
input="x",
message="m",
)
assert format_validation_error_location(error) == "cv.email"
def test_returns_yaml_source_and_single_coordinate_when_schema_location_missing(
self,
):
error = RenderCVValidationError(
schema_location=None,
yaml_location=((3, 7), (3, 7)),
yaml_source="design_yaml_file",
input="x",
message="m",
)
assert format_validation_error_location(error) == "design_yaml_file: line 3"
def test_returns_yaml_source_and_range_when_schema_location_missing(self):
error = RenderCVValidationError(
schema_location=None,
yaml_location=((3, 7), (4, 2)),
yaml_source="main_yaml_file",
input="x",
message="m",
)
assert (
format_validation_error_location(error)
== "main_yaml_file: line 3 to line 4"
)
def test_returns_yaml_source_when_yaml_location_is_missing(self):
error = RenderCVValidationError(
schema_location=None,
yaml_location=None,
yaml_source="locale_yaml_file",
input="x",
message="m",
)
assert format_validation_error_location(error) == "locale_yaml_file"
class TestProgressPanelUpdateProgress:
def test_adds_step_to_completed_steps(self):
panel = ProgressPanel(quiet=True)
test_path = pathlib.Path.cwd() / "output.pdf"
panel.update_progress("100", "Generated PDF", [test_path])
assert len(panel.completed_steps) == 1
assert panel.completed_steps[0].timing_ms == "100"
assert panel.completed_steps[0].message == "Generated PDF"
assert panel.completed_steps[0].paths == [test_path]
def test_handles_multiple_paths(self):
panel = ProgressPanel(quiet=True)
path1 = pathlib.Path.cwd() / "page1.png"
path2 = pathlib.Path.cwd() / "page2.png"
panel.update_progress("250", "Generated PNG", [path1, path2])
assert len(panel.completed_steps) == 1
assert panel.completed_steps[0].paths == [path1, path2]
def test_handles_empty_paths(self):
panel = ProgressPanel(quiet=True)
panel.update_progress("50", "Validated input", [])
assert len(panel.completed_steps) == 1
assert panel.completed_steps[0].paths == []
class TestProgressPanelFinishProgress:
def test_clears_completed_steps(self):
panel = ProgressPanel(quiet=True)
panel.completed_steps.append(
CompletedStep("100", "Test", [pathlib.Path.cwd() / "test.pdf"])
)
panel.finish_progress()
assert len(panel.completed_steps) == 0
class TestProgressPanelPrintProgressPanel:
def test_quiet_mode_produces_no_output(self, capsys):
with ProgressPanel(quiet=True) as panel:
panel.update_progress("100", "Test", [])
panel.finish_progress()
captured = capsys.readouterr()
assert captured.out == ""
def test_respects_quiet_mode(self):
panel = ProgressPanel(quiet=True)
panel.completed_steps.append(CompletedStep("100", "Test", []))
panel.print_progress_panel("Test Title")
def test_displays_step_without_paths(self):
panel = ProgressPanel(quiet=True)
panel.completed_steps.append(CompletedStep("100", "Validated input", []))
# This should not raise an error
panel.print_progress_panel("Rendering your CV...")
def test_displays_step_with_single_path(self):
panel = ProgressPanel(quiet=True)
test_path = pathlib.Path.cwd() / "output.pdf"
panel.completed_steps.append(CompletedStep("250", "Generated PDF", [test_path]))
panel.print_progress_panel("Rendering your CV...")
def test_displays_step_with_multiple_paths(self):
panel = ProgressPanel(quiet=True)
path1 = pathlib.Path.cwd() / "page1.png"
path2 = pathlib.Path.cwd() / "page2.png"
panel.completed_steps.append(
CompletedStep("500", "Generated PNG", [path1, path2])
)
panel.print_progress_panel("Rendering your CV...")
def test_displays_multiple_steps(self):
panel = ProgressPanel(quiet=True)
panel.completed_steps.extend(
[
CompletedStep("100", "Step 1", []),
CompletedStep("200", "Step 2", [pathlib.Path.cwd() / "file.txt"]),
CompletedStep("300", "Step 3", []),
]
)
panel.print_progress_panel("Rendering your CV...")
def test_handles_empty_steps(self):
panel = ProgressPanel(quiet=True)
panel.print_progress_panel("Rendering your CV...")
class TestProgressPanelPrintUserError:
def test_exits_with_code_1(self):
panel = ProgressPanel(quiet=True)
error = RenderCVUserError(message="Test error message")
with pytest.raises(typer.Exit) as exc_info:
panel.print_user_error(error)
assert exc_info.value.exit_code == 1
def test_handles_error_without_message(self):
panel = ProgressPanel(quiet=True)
error = RenderCVUserError(message=None)
with pytest.raises(typer.Exit) as exc_info:
panel.print_user_error(error)
assert exc_info.value.exit_code == 1
class TestProgressPanelPrintValidationErrors:
def test_exits_with_code_1(self):
panel = ProgressPanel(quiet=True)
errors: list[RenderCVValidationError] = [
RenderCVValidationError(
schema_location=("cv", "name"),
yaml_location=((1, 1), (1, 1)),
yaml_source="main_yaml_file",
input="123",
message="Invalid name",
)
]
with pytest.raises(typer.Exit) as exc_info:
panel.print_validation_errors(errors)
assert exc_info.value.exit_code == 1
def test_clears_completed_steps_before_displaying_errors(self):
panel = ProgressPanel(quiet=True)
panel.completed_steps.append(
CompletedStep("100", "Test", [pathlib.Path.cwd() / "test.pdf"])
)
errors: list[RenderCVValidationError] = [
RenderCVValidationError(
schema_location=("cv", "name"),
yaml_location=((1, 1), (1, 1)),
yaml_source="main_yaml_file",
input="123",
message="Invalid name",
)
]
with pytest.raises(typer.Exit):
panel.print_validation_errors(errors)
# We can't check this after the exception, but the implementation shows
# it clears steps before displaying
def test_handles_multiple_validation_errors(self):
panel = ProgressPanel(quiet=True)
errors: list[RenderCVValidationError] = [
RenderCVValidationError(
schema_location=("cv", "name"),
yaml_location=((1, 1), (1, 1)),
yaml_source="main_yaml_file",
input="123",
message="Invalid name",
),
RenderCVValidationError(
schema_location=("cv", "email"),
yaml_location=((2, 1), (2, 1)),
yaml_source="main_yaml_file",
input="not-an-email",
message="Invalid email format",
),
]
with pytest.raises(typer.Exit) as exc_info:
panel.print_validation_errors(errors)
assert exc_info.value.exit_code == 1
def test_handles_yaml_parse_error_with_no_location(self):
panel = ProgressPanel(quiet=True)
errors: list[RenderCVValidationError] = [
RenderCVValidationError(
schema_location=None,
yaml_location=((3, 7), (3, 7)),
yaml_source="main_yaml_file",
input="...",
message="This is not a valid YAML file.",
)
]
with pytest.raises(typer.Exit) as exc_info:
panel.print_validation_errors(errors)
assert exc_info.value.exit_code == 1
class TestProgressPanelClear:
def test_clears_completed_steps(self):
panel = ProgressPanel(quiet=True)
panel.completed_steps.extend(
[
CompletedStep("100", "Step 1", []),
CompletedStep("200", "Step 2", []),
]
)
panel.clear()
assert len(panel.completed_steps) == 0
class TestCompletedStep:
def test_creates_step_without_paths(self):
step = CompletedStep("100", "Validated input", [])
assert step.timing_ms == "100"
assert step.message == "Validated input"
assert step.paths == []
def test_creates_step_with_paths(self):
test_path = pathlib.Path.cwd() / "output.pdf"
step = CompletedStep("250", "Generated PDF", [test_path])
assert step.timing_ms == "250"
assert step.message == "Generated PDF"
assert step.paths == [test_path]