Skip to content

Commit 855dcb7

Browse files
committed
Add prompts loader tests and lazy command build for CLAUDE.md fixer
Signed-off-by: ddjain <darjain@redhat.com>
1 parent 98eecb5 commit 855dcb7

5 files changed

Lines changed: 49 additions & 8 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ src/agentready/
4646
├── reporters/ # Report generation (HTML, Markdown, JSON)
4747
│ ├── html.py # Interactive HTML with Jinja2
4848
│ └── markdown.py # GitHub-Flavored Markdown
49+
├── prompts/ # LLM prompt .md templates; load_prompt(name) from loader.py
4950
├── templates/ # Jinja2 templates
5051
│ └── report.html.j2 # Self-contained HTML report (73KB)
5152
└── cli/ # Click-based CLI

src/agentready/fixers/documentation.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@ def _claude_md_command() -> str:
3333
]
3434
)
3535

36-
# Command run by CLAUDEmdFixer to generate CLAUDE.md via Claude CLI
37-
CLAUDE_MD_COMMAND = _claude_md_command()
38-
3936

4037
class _ClaudeMdToAgentRedirectFix(Fix):
4138
"""Post-step fix: move CLAUDE.md content to AGENTS.md, replace CLAUDE.md with @AGENTS.md."""
@@ -152,7 +149,7 @@ def generate_fix(self, repository: Repository, finding: Finding) -> Optional[Fix
152149
attribute_id=self.attribute_id,
153150
description="Run Claude CLI to create CLAUDE.md in the project",
154151
points_gained=points,
155-
command=CLAUDE_MD_COMMAND,
152+
command=_claude_md_command(),
156153
working_dir=repository.path,
157154
repository_path=repository.path,
158155
capture_output=False, # Stream Claude output to terminal

src/agentready/prompts/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
"""LLM prompt templates loaded from package resources."""
22

3-
import importlib.resources
4-
53
from .loader import load_prompt
64

75
__all__ = ["load_prompt"]

tests/unit/test_fixers.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99

1010
from agentready.fixers.documentation import (
1111
ANTHROPIC_API_KEY_ENV,
12-
CLAUDE_MD_COMMAND,
1312
CLAUDE_MD_REDIRECT_LINE,
1413
CLAUDEmdFixer,
1514
GitignoreFixer,
15+
_claude_md_command,
1616
)
1717
from agentready.models.attribute import Attribute
1818
from agentready.models.finding import Finding, Remediation
@@ -107,6 +107,14 @@ def gitignore_failing_finding():
107107
)
108108

109109

110+
def test_claude_md_command_shell_safe():
111+
"""_claude_md_command returns a command with shell-quoted arguments."""
112+
cmd = _claude_md_command()
113+
assert "claude" in cmd
114+
assert "-p" in cmd
115+
assert "'" in cmd or '"' in cmd # shlex.quote applied
116+
117+
110118
class TestCLAUDEmdFixer:
111119
"""Tests for CLAUDEmdFixer."""
112120

@@ -142,7 +150,7 @@ def test_generate_fix_when_agent_md_missing(
142150
assert isinstance(fix, MultiStepFix)
143151
assert len(fix.steps) == 2
144152
assert isinstance(fix.steps[0], CommandFix)
145-
assert fix.steps[0].command == CLAUDE_MD_COMMAND
153+
assert fix.steps[0].command == _claude_md_command()
146154
assert fix.steps[0].working_dir == temp_repo.path
147155
assert fix.steps[0].capture_output is False
148156
assert fix.attribute_id == "claude_md_file"

tests/unit/test_prompts_loader.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""Unit tests for prompts loader."""
2+
3+
import importlib.resources
4+
5+
import pytest
6+
7+
from agentready.prompts import load_prompt
8+
9+
10+
def test_load_prompt_success():
11+
"""load_prompt returns content for existing prompt file."""
12+
content = load_prompt("claude_md_generator")
13+
assert content
14+
assert "senior technical documentation architect" in content
15+
assert "CLAUDE.md" in content
16+
17+
18+
def test_load_prompt_invalid_name_raises_value_error():
19+
"""load_prompt raises ValueError for names with path separators or leading dot."""
20+
with pytest.raises(ValueError, match="Invalid prompt name"):
21+
load_prompt("../malicious")
22+
with pytest.raises(ValueError, match="Invalid prompt name"):
23+
load_prompt("foo/bar")
24+
with pytest.raises(ValueError, match="Invalid prompt name"):
25+
load_prompt(".hidden")
26+
27+
28+
def test_load_prompt_missing_file_raises_file_not_found_error():
29+
"""load_prompt raises FileNotFoundError for non-existent prompt."""
30+
with pytest.raises(FileNotFoundError, match="nonexistent_prompt"):
31+
load_prompt("nonexistent_prompt")
32+
33+
34+
def test_prompts_packaged_correctly():
35+
"""Ensure .md prompt files are included in package distribution."""
36+
ref = importlib.resources.files("agentready.prompts")
37+
assert (ref / "claude_md_generator.md").is_file()

0 commit comments

Comments
 (0)