Skip to content

Commit 0e0ffa0

Browse files
Kasper JungeRalphify
authored andcommitted
test: add missing edge case coverage for _runner module
Add tests for FileNotFoundError propagation, empty string command validation, and timeout with captured partial output — three untested code paths in run_command(). Co-authored-by: Ralphify <noreply@ralphify.co>
1 parent 2502e45 commit 0e0ffa0

3 files changed

Lines changed: 36 additions & 0 deletions

File tree

src/ralphify/_frontmatter.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,13 @@ def parse_frontmatter(text: str) -> tuple[dict[str, Any], str]:
7171
Full YAML is supported (nested lists, dicts). HTML comments are
7272
stripped from the body so they don't leak into the assembled prompt.
7373
74+
A leading UTF-8 BOM (``\\ufeff``) is stripped so files saved with a
75+
BOM (common on Windows) are handled transparently.
76+
7477
Returns ``(frontmatter_dict, body_text)``.
7578
"""
79+
if text.startswith("\ufeff"):
80+
text = text[1:]
7681
fm_raw, body = _extract_frontmatter_block(text)
7782
if fm_raw:
7883
try:

tests/test_frontmatter.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ def test_block_scalar_with_triple_dash_parsed_correctly(self):
134134
assert "---" in fm["notes"]
135135
assert body == "Body"
136136

137+
def test_utf8_bom_does_not_break_frontmatter(self):
138+
"""Files saved with a UTF-8 BOM (common on Windows) must still
139+
have their frontmatter parsed correctly."""
140+
text = "\ufeff---\nagent: claude\n---\nDo the thing"
141+
fm, body = parse_frontmatter(text)
142+
assert fm == {"agent": "claude"}
143+
assert body == "Do the thing"
144+
137145
def test_non_dict_frontmatter_raises_value_error(self):
138146
text = "---\n- item1\n- item2\n---\nBody"
139147
with pytest.raises(ValueError, match="must be a YAML mapping"):

tests/test_runner.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,26 @@ def test_env_none_inherits_parent(self, mock_run):
9090
def test_raises_when_command_is_whitespace_only(self):
9191
with pytest.raises(ValueError, match="no tokens after parsing"):
9292
run_command(command=" ", cwd=Path("/project"), timeout=60)
93+
94+
def test_raises_when_command_is_empty_string(self):
95+
with pytest.raises(ValueError, match="no tokens after parsing"):
96+
run_command(command="", cwd=Path("/project"), timeout=60)
97+
98+
@patch(MOCK_RUNNER_SUBPROCESS)
99+
def test_file_not_found_propagates(self, mock_run):
100+
mock_run.side_effect = FileNotFoundError("No such file")
101+
with pytest.raises(FileNotFoundError, match="No such file"):
102+
run_command(command="nonexistent-binary", cwd=Path("/project"), timeout=60)
103+
104+
@patch(MOCK_RUNNER_SUBPROCESS)
105+
def test_timeout_preserves_captured_output(self, mock_run):
106+
exc = subprocess.TimeoutExpired(cmd="slow", timeout=5)
107+
exc.stdout = "partial out\n"
108+
exc.stderr = "partial err\n"
109+
mock_run.side_effect = exc
110+
result = run_command(command="slow", cwd=Path("/project"), timeout=5)
111+
112+
assert result.timed_out is True
113+
assert result.returncode is None
114+
assert "partial out" in result.output
115+
assert "partial err" in result.output

0 commit comments

Comments
 (0)