From 89dd3d69a6fca67be59a74f3f6d70719fdfdc5d8 Mon Sep 17 00:00:00 2001 From: Tony Blank Date: Fri, 13 Jun 2025 11:35:56 -0600 Subject: [PATCH] Enhance documentation and CLI help text formatting - Added best practices for Click CLI help text formatting in CLAUDE.md, including key principles, formatting templates, and common issues. - Updated README.md to include smart PR detection and troubleshooting sections for authentication issues and common errors. - Improved command documentation in cli.py, fetch.py, reply.py, and resolve.py with consistent formatting and examples. - Adjusted test assertions in various CLI tests to reflect updated documentation and ensure accuracy in help text outputs. These changes aim to improve user guidance and enhance the overall clarity of the CLI documentation. --- CLAUDE.md | 61 ++++++++ README.md | 45 ++++++ src/toady/cli.py | 94 ++++++------ src/toady/commands/fetch.py | 112 +++++++------- src/toady/commands/reply.py | 138 +++++++++--------- src/toady/commands/resolve.py | 124 ++++++++-------- tests/integration/cli/test_fetch_cli.py | 2 +- tests/integration/cli/test_reply_cli.py | 6 +- tests/integration/cli/test_resolve_cli.py | 2 +- .../real_api/test_end_to_end_workflows.py | 17 ++- tests/unit/commands/test_reply.py | 4 +- tests/unit/test_cli.py | 14 +- 12 files changed, 373 insertions(+), 246 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8c775e8..13ba42f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -192,6 +192,67 @@ mypy toady/ This guide ensures elegant, maintainable, and well-tested development of toady-cli. +## Click CLI Help Text Formatting Best Practices + +### Key Principles +1. **Use `\b` for preserved formatting** - Prevents Click from rewrapping specific sections +2. **Structure with clear sections** - Use consistent headings like "Examples:", "Options:", "Behavior:" +3. **Provide concrete examples** - Show real command usage, not abstract descriptions +4. **Use consistent indentation** - 2 spaces for section content, 4 spaces for nested items +5. **Keep sections focused** - Each `\b` block should be a logical unit + +### Formatting Template +```python +@click.command() +def example(): + """Brief command description. + + Longer explanation of what the command does and its purpose. + + \b + Behavior: + • Key behavior point 1 + • Key behavior point 2 + • Key behavior point 3 + + \b + Examples: + Basic usage: + command --option value + + Advanced usage: + command --option1 value1 --option2 value2 + + \b + Error codes: + • error_type_1: Description of when this occurs + • error_type_2: Description of when this occurs + """ +``` + +### Key Formatting Rules +- **Use `\b` before each major section** to preserve formatting +- **Use bullet points (•)** for lists instead of dashes or asterisks +- **Indent consistently**: 2 spaces for section headers, 4 spaces for content +- **Separate code examples** with proper indentation (4-6 spaces) +- **Use quotes consistently**: Single quotes for command names, double quotes for strings +- **Keep lines under 80 characters** when possible for terminal compatibility + +### Section Order +1. Brief description (1-2 sentences) +2. Detailed explanation +3. Behavior/Operation modes +4. Examples (most important section) +5. Agent usage patterns (for automation) +6. Validation/Safety notes +7. Error codes + +### Common Issues and Solutions +- **Text wrapping problems**: Use `\b` before each section that needs preserved formatting +- **Inconsistent indentation**: Use 2 spaces for headers, 4+ spaces for code blocks +- **Poor readability**: Break large sections into smaller focused blocks with `\b` +- **Example clarity**: Always show complete, runnable command examples + ## Git Commit and PR Guidelines ### Commit Messages and PR Descriptions diff --git a/README.md b/README.md index aa17cae..564a295 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,19 @@ toady resolve --thread-id abc123def --undo toady resolve --all --pr 123 ``` +### Smart PR Detection + +```bash +# Toady automatically detects your PR context: +# - Single PR: fetches automatically +# - Multiple PRs: shows interactive selection +# - No PRs: displays helpful message +toady fetch + +# Override auto-detection for specific PR +toady fetch --pr 123 +``` + ### Schema Validation ```bash @@ -243,6 +256,38 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file For more detailed documentation, visit our [GitHub Wiki](https://github.com/tonyblank/toady-cli/wiki). +## 🛮️ Troubleshooting + +### Authentication Issues + +- **Run:** `gh auth login` +- **Verify:** `gh auth status` +- **Ensure repo scope:** `gh auth login --scopes repo` + +### Common Errors + +- **"authentication_required":** GitHub CLI not logged in +- **"pr_not_found":** PR doesn't exist or no repository access +- **"rate_limit_exceeded":** Too many API calls, wait and retry +- **"thread_not_found":** Invalid thread ID or thread was deleted + +### Debug Mode + +- **Set TOADY_DEBUG=1** or use `--debug` flag for detailed error info +- **Use `--format pretty`** for human-readable output during testing + +### ID Issues + +- **Always use thread IDs** from `toady fetch` output +- **Use `toady reply --help-ids`** for complete ID documentation +- **Thread IDs** (PRRT_, PRT_, RT_) are more reliable than comment IDs + +### Rate Limiting + +- **Use `--limit` option** to reduce API calls +- **Add delays** between operations in scripts +- **Check limits:** `gh api rate_limit` + ## 🐛 Bug Reports Found a bug? Please [open an issue](https://github.com/tonyblank/toady-cli/issues/new) with a clear description and steps to reproduce. diff --git a/src/toady/cli.py b/src/toady/cli.py index fc31748..b832726 100644 --- a/src/toady/cli.py +++ b/src/toady/cli.py @@ -24,66 +24,68 @@ def cli(ctx: click.Context, debug: bool) -> None: """Toady - GitHub PR review management tool. Efficiently manage GitHub pull request code reviews from the command line. - Integrates with GitHub CLI (`gh`) to fetch, reply to, and resolve review threads. - - PREREQUISITES: - • GitHub CLI (`gh`) must be installed and authenticated - • Run `gh auth login` if not already authenticated - • Ensure you have access to the target repository - - CORE WORKFLOW: - 1. Fetch review threads: `toady fetch --pr 123` - 2. Reply to comments: `toady reply --id --body "Fixed!"` - 3. Resolve threads: `toady resolve --thread-id ` - - AGENT-FRIENDLY USAGE: - • All commands output JSON by default for easy parsing - • Use `--format pretty` for human-readable output - • Thread and comment IDs are consistently formatted - • Error responses include structured error codes - - COMMON PATTERNS: - Interactive workflow: - toady fetch # Select PR interactively - toady reply --id --body "Response" - toady resolve --thread-id - - Automated workflow: - toady fetch --pr 123 --format json | jq '.[] | .thread_id' - toady reply --id --body "Automated response" - toady resolve --all --pr 123 --yes - - For detailed command help: toady --help - For examples and patterns: see examples.md in project repository - - TROUBLESHOOTING: - - Authentication Issues: + Integrates with GitHub CLI (gh) to fetch, reply to, and resolve review threads. + + \b + Prerequisites: + • GitHub CLI (gh) must be installed and authenticated + • Run 'gh auth login' if not already authenticated + • Ensure you have access to the target repository + + \b + Core workflow: + 1. Fetch review threads: toady fetch + 2. Reply to comments: toady reply --id --body "Fixed!" + 3. Resolve threads: toady resolve --thread-id + + \b + Agent-friendly usage: + • All commands output JSON by default for easy parsing + • Use --format pretty for human-readable output + • Thread and comment IDs are consistently formatted + • Error responses include structured error codes + + \b + Common patterns: + \b + Interactive workflow: + toady fetch # Auto-detect PR + toady reply --id --body "Response" + toady resolve --thread-id + \b + Automated workflow: + toady fetch | jq '.[] | .thread_id' + toady reply --id --body "Automated response" + toady resolve --all --pr 123 --yes + \b + Troubleshooting: + \b + Authentication issues: • Run: gh auth login • Verify: gh auth status • Ensure repo scope: gh auth login --scopes repo - - Common Errors: + \b + Common errors: • "authentication_required": GitHub CLI not logged in • "pr_not_found": PR doesn't exist or no repository access • "rate_limit_exceeded": Too many API calls, wait and retry • "thread_not_found": Invalid thread ID or thread was deleted - - Debug Mode: + \b + Debug mode: • Set TOADY_DEBUG=1 or use --debug flag for detailed error info • Use --format pretty for human-readable output during testing - - ID Issues: - • Always use thread IDs from `toady fetch` output - • Use `toady reply --help-ids` for complete ID documentation + \b + ID issues: + • Always use thread IDs from 'toady fetch' output + • Use 'toady reply --help-ids' for complete ID documentation • Thread IDs (PRRT_, PRT_, RT_) are more reliable than comment IDs - - Rate Limiting: + \b + Rate limiting: • Use --limit option to reduce API calls • Add delays between operations in scripts • Check limits: gh api rate_limit - For comprehensive examples: see examples.md + For detailed command help: toady --help """ ctx.ensure_object(dict) ctx.obj["debug"] = debug diff --git a/src/toady/commands/fetch.py b/src/toady/commands/fetch.py index f4c28c4..0d66318 100644 --- a/src/toady/commands/fetch.py +++ b/src/toady/commands/fetch.py @@ -54,69 +54,73 @@ def fetch( ) -> None: """Fetch review threads from a GitHub pull request. - Retrieves review threads (comments that require responses) from GitHub PRs. - Returns structured data containing thread IDs, comment content, authors, and - metadata. - - BEHAVIOR: - • Without --pr: Shows interactive PR selection menu - • With --pr: Fetches from specified pull request number - • Default: Only unresolved threads (threads needing responses) - • With --resolved: Includes both resolved and unresolved threads - - OUTPUT STRUCTURE (JSON): - [ - { - "thread_id": "PRRT_kwDOO3WQIc5Rv3_r", # Use for replies/resolve - "comment_id": "IC_kwDOABcD12MAAAABcDE3fg", # Alternative ID - "body": "Please fix this issue", - "author": "reviewer-username", - "created_at": "2023-01-01T12:00:00Z", - "is_resolved": false, - "pr_number": 123, - "file_path": "src/main.py", - "line_number": 42 - } - ] - - AGENT USAGE PATTERNS: - # Get unresolved threads for processing + Automatically detects and fetches review threads from GitHub PRs. When run + without arguments, intelligently selects the appropriate PR or prompts for + selection when multiple PRs exist. + + \b + Behavior: + • Default: Auto-detects PR (single PR: fetches automatically, multiple: prompts) + • With --pr: Fetches from specified pull request number + • Default: Only unresolved threads (threads needing responses) + • With --resolved: Includes both resolved and unresolved threads + + \b + Output structure (JSON): + [ + { + "thread_id": "PRRT_kwDOO3WQIc5Rv3_r", # Use for replies/resolve + "comment_id": "IC_kwDOABcD12MAAAABcDE3fg", # Alternative ID + "body": "Please fix this issue", + "author": "reviewer-username", + "created_at": "2023-01-01T12:00:00Z", + "is_resolved": false, + "pr_number": 123, + "file_path": "src/main.py", + "line_number": 42 + } + ] + + \b + Examples: + Auto-detect PR (recommended): + toady fetch + + Human-readable output: + toady fetch --format pretty + + Specific PR: toady fetch --pr 123 - # Get all thread IDs for bulk operations - toady fetch --pr 123 | jq '.[].thread_id' + Include resolved threads: + toady fetch --resolved - # Find threads by author - toady fetch --pr 123 | jq '.[] | select(.author == "reviewer")' + Limit results: + toady fetch --limit 50 - INTERACTIVE USAGE: - toady fetch --format pretty # Human-readable output with colors + Pipeline with other tools: + toady fetch | jq '.[].thread_id' | xargs -I {} toady resolve --thread-id {} - EXAMPLES: - Basic fetch (JSON output): - toady fetch --pr 123 + \b + Agent usage patterns: + # Get unresolved threads for processing + toady fetch - Human-readable output: - toady fetch --pr 123 --format pretty + # Get all thread IDs for bulk operations + toady fetch | jq '.[].thread_id' - Include resolved threads: - toady fetch --pr 123 --resolved + # Find threads by author + toady fetch | jq '.[] | select(.author == "reviewer")' - Limit results: - toady fetch --pr 123 --limit 50 + # Target specific PR when multiple exist + toady fetch --pr 123 - Interactive PR selection: - toady fetch - - Pipeline with other tools: - toady fetch --pr 123 | jq '.[].thread_id' | \\ - xargs -I {} toady resolve --thread-id {} - - ERROR CODES: - • authentication_required: GitHub CLI not authenticated - • pr_not_found: Pull request doesn't exist or no access - • no_threads_found: PR has no review threads - • api_rate_limit: GitHub API rate limit exceeded + \b + Error codes: + • authentication_required: GitHub CLI not authenticated + • pr_not_found: Pull request doesn't exist or no access + • no_threads_found: PR has no review threads + • api_rate_limit: GitHub API rate limit exceeded """ # Validate input parameters if pr_number is not None: diff --git a/src/toady/commands/reply.py b/src/toady/commands/reply.py index a29669e..ebc06b9 100644 --- a/src/toady/commands/reply.py +++ b/src/toady/commands/reply.py @@ -53,7 +53,7 @@ def _show_id_help(ctx: click.Context) -> None: 🔍 HOW TO FIND THE RIGHT ID: 1. Use the fetch command: - toady fetch --pr --pretty + toady fetch --format pretty 2. Look for: • "Thread ID:" for thread-level replies (recommended) @@ -82,7 +82,7 @@ def _show_id_help(ctx: click.Context) -> None: 🆘 TROUBLESHOOTING: If you get an error about PRRC_ IDs: -1. Run: toady fetch --pr --pretty +1. Run: toady fetch --format pretty 2. Find the "Thread ID" for that comment 3. Use the thread ID instead @@ -124,7 +124,7 @@ def validate_reply_target_id(reply_to_id: str) -> str: "Individual comment IDs from submitted reviews (PRRC_) " "cannot be replied to directly.\n" "\n💡 Use the thread ID instead:\n" - " • Run: toady fetch --pr --pretty\n" + " • Run: toady fetch --format pretty\n" " • Look for the thread ID (starts with PRRT_, PRT_, or RT_)\n" " • Use that thread ID with --id\n" "\n📖 For more help with ID types, use: toady reply --help-ids", @@ -145,7 +145,7 @@ def validate_reply_target_id(reply_to_id: str) -> str: " • Comment IDs: IC_, RP_ (individual comments)\n" " • Numeric IDs: 123456789 (legacy format)\n\n" "🔍 To find the correct ID:\n" - " • Run: toady fetch --pr --pretty\n" + " • Run: toady fetch --format pretty\n" " • Look for 'Thread ID' or 'Comment ID' in the output\n\n" "📖 For detailed ID help: toady reply --help-ids" ) @@ -508,68 +508,74 @@ def reply( Creates a new comment in response to an existing review thread or comment. Supports various ID formats and provides structured response data. - ID TYPES SUPPORTED: - • Thread IDs: PRRT_, PRT_, RT_ (recommended - most reliable) - • Comment IDs: IC_, RP_ (for individual comments) - • Numeric IDs: 123456789 (legacy GitHub comment IDs) - - IMPORTANT RESTRICTIONS: - • PRRC_ IDs (individual review comments) cannot be replied to directly - • For submitted reviews, always use thread IDs (PRRT_, PRT_, RT_) - • Use thread IDs from `toady fetch` output for best compatibility - - OUTPUT STRUCTURE (JSON): - { - "id": "PRRT_kwDOO3WQIc5Rv3_r", # Original target ID - "success": true, - "reply_posted": true, - "reply_id": "IC_kwDOABcD12MAAAABcDE3fg", # New reply ID - "reply_url": "https://github.com/owner/repo/pull/123#discussion_r987654321", - "created_at": "2023-01-01T12:00:00Z", - "author": "your-username" - } - - AGENT USAGE PATTERNS: - # Standard reply to thread - toady reply --id "PRRT_kwDOO3WQIc5Rv3_r" --body "Fixed in commit abc123" - - # Automated responses - cat responses.txt | while read line; do - toady reply --id "$thread_id" --body "$line" - done - - # Bulk replies with error handling - toady reply --id "$id" --body "$response" || echo "Failed: $id" - - VALIDATION: - • Body: 3-65536 characters, non-empty after trimming - • ID: Must match supported format patterns - • Authentication: Requires GitHub CLI (`gh`) authentication - • Permissions: Must have write access to repository - - EXAMPLES: - Basic reply: - toady reply --id "123456789" --body "Fixed in latest commit" - - Reply to thread (recommended): - toady reply --id "PRRT_kwDOO3WQIc5Rv3_r" --body "Thanks for the review!" - - Reply with verbose output: - toady reply --id "IC_kwDOABcD12MAAAABcDE3fg" --body "Good catch!" --verbose - - Human-readable output: - toady reply --id "PRT_kwDOABcD12MAAAABcDE3fg" \\ - --body "Updated" --format pretty - - Get help with ID types: - toady reply --help-ids - - ERROR CODES: - • comment_not_found: Target comment/thread doesn't exist - • authentication_failed: GitHub CLI not authenticated - • permission_denied: No write access to repository - • validation_error: Invalid ID format or body content - • rate_limit_exceeded: GitHub API rate limit hit + \b + ID types supported: + • Thread IDs: PRRT_, PRT_, RT_ (recommended - most reliable) + • Comment IDs: IC_, RP_ (for individual comments) + • Numeric IDs: 123456789 (legacy GitHub comment IDs) + + \b + Important restrictions: + • PRRC_ IDs (individual review comments) cannot be replied to directly + • For submitted reviews, always use thread IDs (PRRT_, PRT_, RT_) + • Use thread IDs from 'toady fetch' output for best compatibility + + \b + Output structure (JSON): + { + "id": "PRRT_kwDOO3WQIc5Rv3_r", # Original target ID + "success": true, + "reply_posted": true, + "reply_id": "IC_kwDOABcD12MAAAABcDE3fg", # New reply ID + "reply_url": "https://github.com/owner/repo/pull/123#discussion_r987654321", + "created_at": "2023-01-01T12:00:00Z", + "author": "your-username" + } + + \b + Examples: + Basic reply: + toady reply --id "123456789" --body "Fixed in latest commit" + + Reply to thread (recommended): + toady reply --id "PRRT_kwDOO3WQIc5Rv3_r" --body "Thanks for the review!" + + Reply with verbose output: + toady reply --id "IC_kwDOABcD12MAAAABcDE3fg" --body "Good catch!" --verbose + + Human-readable output: + toady reply --id "PRT_kwDOABcD12MAAAABcDE3fg" --body "Updated" --format pretty + + Get help with ID types: + toady reply --help-ids + + \b + Agent usage patterns: + # Standard reply to thread + toady reply --id "PRRT_kwDOO3WQIc5Rv3_r" --body "Fixed in commit abc123" + + # Automated responses + cat responses.txt | while read line; do + toady reply --id "$thread_id" --body "$line" + done + + # Bulk replies with error handling + toady reply --id "$id" --body "$response" || echo "Failed: $id" + + \b + Validation: + • Body: 3-65536 characters, non-empty after trimming + • ID: Must match supported format patterns + • Authentication: Requires GitHub CLI (gh) authentication + • Permissions: Must have write access to repository + + \b + Error codes: + • comment_not_found: Target comment/thread doesn't exist + • authentication_failed: GitHub CLI not authenticated + • permission_denied: No write access to repository + • validation_error: Invalid ID format or body content + • rate_limit_exceeded: GitHub API rate limit hit """ # Show ID help if requested if help_ids: diff --git a/src/toady/commands/resolve.py b/src/toady/commands/resolve.py index 6146a12..ea02e51 100644 --- a/src/toady/commands/resolve.py +++ b/src/toady/commands/resolve.py @@ -634,18 +634,22 @@ def resolve( Changes the resolution status of GitHub review threads, indicating whether the discussion has been addressed. Essential for completing code reviews. - OPERATION MODES: - • Single thread: Use --thread-id to resolve/unresolve one thread - • Bulk operation: Use --all --pr to process all threads in a PR - • Unresolve: Add --undo flag to unresolve instead of resolve - - THREAD ID TYPES: - • Thread IDs: PRT_, PRRT_, RT_ (from `toady fetch` output) - • Numeric IDs: 123456789 (legacy GitHub thread IDs) - • Get IDs from: `toady fetch --pr | jq '.[].thread_id'` - - OUTPUT STRUCTURE (JSON): - Single thread: + \b + Operation modes: + • Single thread: Use --thread-id to resolve/unresolve one thread + • Bulk operation: Use --all --pr to process all threads in a PR + • Unresolve: Add --undo flag to unresolve instead of resolve + + \b + Thread ID types: + • Thread IDs: PRT_, PRRT_, RT_ (from 'toady fetch' output) + • Numeric IDs: 123456789 (legacy GitHub thread IDs) + • Get IDs from: toady fetch | jq '.[].thread_id' + + \b + Output structure (JSON): + + Single thread: { "thread_id": "PRRT_kwDOO3WQIc5RvXMO", "action": "resolve", @@ -654,7 +658,7 @@ def resolve( "thread_url": "https://github.com/owner/repo/pull/123#discussion_r123456" } - Bulk operation: + Bulk operation: { "pr_number": 123, "action": "resolve", @@ -665,53 +669,57 @@ def resolve( "failed_threads": ["RT_kwDOABcD12MAAAABcDE3fg"] } - AGENT USAGE PATTERNS: - # Resolve specific thread - toady resolve --thread-id "PRRT_kwDOO3WQIc5RvXMO" - - # Bulk resolve with error handling - toady resolve --all --pr 123 --yes || echo "Some threads failed" - - # Pipeline: fetch then resolve all - toady fetch --pr 123 | jq -r '.[].thread_id' | while read id; do - toady resolve --thread-id "$id" - done - - VALIDATION & SAFETY: - • Single operations: No confirmation required - • Bulk operations: Confirmation prompt unless --yes flag used - • Thread ID validation: Must match supported format patterns - • Permissions: Requires write access to repository - - EXAMPLES: - Resolve single thread: - toady resolve --thread-id "123456789" - - Resolve with thread node ID: - toady resolve --thread-id "PRRT_kwDOO3WQIc5RvXMO" + \b + Examples: + Resolve single thread: + toady resolve --thread-id "123456789" - Unresolve thread: - toady resolve --thread-id "PRT_kwDOABcD12MAAAABcDE3fg" --undo - - Resolve all threads in PR: - toady resolve --all --pr 123 - - Bulk resolve without confirmation: - toady resolve --all --pr 123 --yes - - Human-readable output: - toady resolve --thread-id "RT_kwDOABcD12MAAAABcDE3fg" --format pretty - - Limited bulk operation: - toady resolve --all --pr 123 --limit 50 + Resolve with thread node ID: + toady resolve --thread-id "PRRT_kwDOO3WQIc5RvXMO" - ERROR CODES: - • thread_not_found: Thread ID doesn't exist or no access - • authentication_failed: GitHub CLI not authenticated - • permission_denied: No write access to repository - • pr_not_found: Pull request doesn't exist (for --all) - • validation_error: Invalid thread ID format - • bulk_operation_partial: Some threads failed in bulk operation + Unresolve thread: + toady resolve --thread-id "PRT_kwDOABcD12MAAAABcDE3fg" --undo + + Resolve all threads in PR: + toady resolve --all --pr 123 + + Bulk resolve without confirmation: + toady resolve --all --pr 123 --yes + + Human-readable output: + toady resolve --thread-id "RT_kwDOABcD12MAAAABcDE3fg" --format pretty + + Limited bulk operation: + toady resolve --all --pr 123 --limit 50 + + \b + Agent usage patterns: + # Resolve specific thread + toady resolve --thread-id "PRRT_kwDOO3WQIc5RvXMO" + + # Bulk resolve with error handling + toady resolve --all --pr 123 --yes || echo "Some threads failed" + + # Pipeline: fetch then resolve all + toady fetch | jq -r '.[].thread_id' | while read id; do + toady resolve --thread-id "$id" + done + + \b + Validation & safety: + • Single operations: No confirmation required + • Bulk operations: Confirmation prompt unless --yes flag used + • Thread ID validation: Must match supported format patterns + • Permissions: Requires write access to repository + + \b + Error codes: + • thread_not_found: Thread ID doesn't exist or no access + • authentication_failed: GitHub CLI not authenticated + • permission_denied: No write access to repository + • pr_not_found: Pull request doesn't exist (for --all) + • validation_error: Invalid thread ID format + • bulk_operation_partial: Some threads failed in bulk operation """ # Resolve format from options try: diff --git a/tests/integration/cli/test_fetch_cli.py b/tests/integration/cli/test_fetch_cli.py index 0e97980..1896283 100644 --- a/tests/integration/cli/test_fetch_cli.py +++ b/tests/integration/cli/test_fetch_cli.py @@ -132,7 +132,7 @@ def test_fetch_help(self, runner: CliRunner) -> None: result = runner.invoke(cli, ["fetch", "--help"]) assert result.exit_code == 0 assert "Fetch review threads from a GitHub pull request" in result.output - assert "EXAMPLES:" in result.output + assert "Examples:" in result.output def test_fetch_pr_parameter_type_validation(self, runner: CliRunner) -> None: """Test that --pr parameter only accepts integers.""" diff --git a/tests/integration/cli/test_reply_cli.py b/tests/integration/cli/test_reply_cli.py index 7023a4c..c2e8e7e 100644 --- a/tests/integration/cli/test_reply_cli.py +++ b/tests/integration/cli/test_reply_cli.py @@ -277,7 +277,7 @@ def test_reply_help_content(self, runner: CliRunner) -> None: result = runner.invoke(cli, ["reply", "--help"]) assert result.exit_code == 0 assert "Post a reply to a specific review comment" in result.output - assert "EXAMPLES:" in result.output + assert "Examples:" in result.output assert "--id" in result.output assert "--body" in result.output @@ -558,7 +558,7 @@ def test_reply_help_ids_flag(self, runner: CliRunner) -> None: assert "NOT SUPPORTED:" in result.output assert "PRRC_kwDOABcD12MAAAABcDE3fg" in result.output assert "HOW TO FIND THE RIGHT ID:" in result.output - assert "toady fetch --pr --pretty" in result.output + assert "toady fetch --format pretty" in result.output assert "TROUBLESHOOTING:" in result.output def test_reply_prrc_id_error_handling(self, runner: CliRunner) -> None: @@ -570,7 +570,7 @@ def test_reply_prrc_id_error_handling(self, runner: CliRunner) -> None: assert result.exit_code == 2 assert "Individual comment IDs from submitted reviews (PRRC_)" in result.output assert "Use the thread ID instead" in result.output - assert "Run: toady fetch --pr --pretty" in result.output + assert "Run: toady fetch --format pretty" in result.output assert ( "Look for the thread ID (starts with PRRT_, PRT_, or RT_)" in result.output ) diff --git a/tests/integration/cli/test_resolve_cli.py b/tests/integration/cli/test_resolve_cli.py index 9c07811..12743c2 100644 --- a/tests/integration/cli/test_resolve_cli.py +++ b/tests/integration/cli/test_resolve_cli.py @@ -368,7 +368,7 @@ def test_resolve_help_content(self, runner: CliRunner) -> None: result = runner.invoke(cli, ["resolve", "--help"]) assert result.exit_code == 0 assert "Mark review threads as resolved or unresolved" in result.output - assert "EXAMPLES:" in result.output + assert "Examples:" in result.output assert "--thread-id" in result.output assert "--undo" in result.output diff --git a/tests/integration/real_api/test_end_to_end_workflows.py b/tests/integration/real_api/test_end_to_end_workflows.py index 18e0a74..6e6885c 100644 --- a/tests/integration/real_api/test_end_to_end_workflows.py +++ b/tests/integration/real_api/test_end_to_end_workflows.py @@ -331,15 +331,16 @@ def test_interactive_workflow_with_multiple_prs( # Should either work with available PRs or skip gracefully if result.exit_code == 0: - # Verify we got valid thread data + # Verify we got valid thread data, or empty output (user cancelled/no PRs) # For JSON format, check stdout only (stderr contains interactive messages) - try: - raw_out = getattr(result, "stdout", result.output) - threads_data = json.loads(raw_out) - assert isinstance(threads_data, list) - except json.JSONDecodeError: - raw_out = getattr(result, "stdout", result.output) - pytest.fail(f"Invalid JSON response in output: {raw_out}") + raw_out = getattr(result, "stdout", result.output) + if raw_out.strip(): # Only parse if there's actual output + try: + threads_data = json.loads(raw_out) + assert isinstance(threads_data, list) + except json.JSONDecodeError: + pytest.fail(f"Invalid JSON response in output: {raw_out}") + # Empty output is valid when user cancels or no PRs available else: # Interactive mode might fail if no PRs available - that's okay assert ( diff --git a/tests/unit/commands/test_reply.py b/tests/unit/commands/test_reply.py index 122c397..60f3795 100644 --- a/tests/unit/commands/test_reply.py +++ b/tests/unit/commands/test_reply.py @@ -502,9 +502,9 @@ def test_id_help_content(self, capsys): assert "NOT SUPPORTED:" in captured.out assert "PRRC_kwDOABcD12MAAAABcDE3fg" in captured.out assert "HOW TO FIND THE RIGHT ID:" in captured.out - assert "toady fetch --pr --pretty" in captured.out + assert "toady fetch --format pretty" in captured.out assert "BEST PRACTICES:" in captured.out - assert "EXAMPLES:" in captured.out + assert "📚 EXAMPLES:" in captured.out assert "TROUBLESHOOTING:" in captured.out ctx.exit.assert_called_once_with(0) diff --git a/tests/unit/test_cli.py b/tests/unit/test_cli.py index 130b9fd..f7beb22 100644 --- a/tests/unit/test_cli.py +++ b/tests/unit/test_cli.py @@ -60,9 +60,9 @@ def test_cli_docstring_present(self): """Test that CLI has comprehensive help documentation.""" assert cli.help is not None assert "Toady - GitHub PR review management tool" in cli.help - assert "PREREQUISITES:" in cli.help - assert "CORE WORKFLOW:" in cli.help - assert "TROUBLESHOOTING:" in cli.help + assert "Prerequisites:" in cli.help + assert "Core workflow:" in cli.help + assert "Troubleshooting:" in cli.help class TestCLIGroupFunctionality: @@ -373,10 +373,10 @@ def test_cli_help_structure(self, runner): "Usage:", "Options:", "Commands:", - "PREREQUISITES:", - "CORE WORKFLOW:", - "AGENT-FRIENDLY USAGE:", - "TROUBLESHOOTING:", + "Prerequisites:", + "Core workflow:", + "Agent-friendly usage:", + "Troubleshooting:", ] for section in expected_sections: