feat: Implement comprehensive IssueCreator system and create CLI roadmap issues
IssueCreator Implementation: - Add tddai/issue_creator.py with full POST API functionality for issue creation - Support multiple creation methods: basic, enhancement, bug, template-based - Include structured issue formatting with acceptance criteria and dependencies - Template system with variable substitution for reusable issue creation Authentication Fix: - Fix critical authentication bug: use GITEA_API_TOKEN instead of GITEA_TOKEN - Update both IssueCreator and IssueWriter for consistency - Update all tests and documentation to reflect correct environment variable Comprehensive Test Suite: - Add 15 unit tests for IssueCreator (tests/test_issue_creator.py) - Add 5 integration tests for full API lifecycle (tests/test_issue_integration.py) - Create test_environment_variable_detection to prevent future auth issues - Total 33 tests covering complete issue handling workflow CLI Integration: - Enhance tddai_cli.py with 3 new commands: create-issue, create-enhancement, create-from-template - Add comprehensive argument parsing with optional fields and priority support - Include user-friendly output with next step guidance - Update package exports to include IssueCreator CLI Roadmap Execution: - Successfully create 8 CLI implementation issues (#12-#19) in Gitea - Resolve mismatch between NEXT.md roadmap and actual Gitea issues - Issues prioritized for core USPs: Database Query CLI and AST Query CLI - Remove local MISSING_ISSUES.md file after successful creation Framework Maturity: - Complete CRUD operations for issue management (Create, Read, Update, Delete) - Robust error handling and API integration patterns - Full authentication and environment variable management - Ready for production CLI implementation workflow 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
163
tests/test_issue_integration.py
Normal file
163
tests/test_issue_integration.py
Normal file
@@ -0,0 +1,163 @@
|
||||
"""
|
||||
Integration tests for issue creation, retrieval, and management workflow.
|
||||
|
||||
This test validates the complete issue lifecycle to catch authentication
|
||||
and API integration issues.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from tddai.issue_creator import IssueCreator
|
||||
from tddai.issue_writer import IssueWriter
|
||||
from tddai.issue_fetcher import IssueFetcher
|
||||
from tddai.config import TddaiConfig
|
||||
from tddai.exceptions import IssueError
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
class TestIssueIntegration:
|
||||
"""Integration tests for the complete issue workflow."""
|
||||
|
||||
def _get_test_config(self):
|
||||
"""Get test configuration."""
|
||||
return TddaiConfig(
|
||||
workspace_dir=Path(".test_workspace"),
|
||||
gitea_url="http://92.205.130.254:32166",
|
||||
repo_owner="coulomb",
|
||||
repo_name="markitect_project"
|
||||
)
|
||||
|
||||
@pytest.fixture
|
||||
def auth_token(self):
|
||||
"""Get auth token from environment."""
|
||||
token = os.getenv('GITEA_API_TOKEN')
|
||||
if not token:
|
||||
pytest.skip("GITEA_API_TOKEN environment variable not set")
|
||||
return token
|
||||
|
||||
def test_environment_variable_detection(self):
|
||||
"""Test that components correctly detect GITEA_API_TOKEN."""
|
||||
config = self._get_test_config()
|
||||
|
||||
# Test without token
|
||||
creator_no_token = IssueCreator(config=config)
|
||||
writer_no_token = IssueWriter(config=config)
|
||||
|
||||
token_available = os.getenv('GITEA_API_TOKEN') is not None
|
||||
|
||||
if token_available:
|
||||
assert creator_no_token.auth_token is not None, "IssueCreator should detect GITEA_API_TOKEN"
|
||||
assert writer_no_token.auth_token is not None, "IssueWriter should detect GITEA_API_TOKEN"
|
||||
assert creator_no_token.auth_token == writer_no_token.auth_token, "Both should use same token"
|
||||
else:
|
||||
assert creator_no_token.auth_token is None, "Should be None when token not available"
|
||||
assert writer_no_token.auth_token is None, "Should be None when token not available"
|
||||
|
||||
def test_complete_issue_lifecycle(self, auth_token):
|
||||
"""Test create -> retrieve -> update -> delete cycle."""
|
||||
config = self._get_test_config()
|
||||
creator = IssueCreator(config=config, auth_token=auth_token)
|
||||
writer = IssueWriter(config=config, auth_token=auth_token)
|
||||
fetcher = IssueFetcher(config=config)
|
||||
|
||||
# Step 1: Create a test issue
|
||||
test_title = f"Test Issue - Integration Test {int(time.time())}"
|
||||
test_body = "This is a test issue created by integration tests. Please ignore and delete."
|
||||
|
||||
created_issue = creator.create_issue(
|
||||
title=test_title,
|
||||
body=test_body,
|
||||
labels=["test", "integration"]
|
||||
)
|
||||
|
||||
assert 'number' in created_issue, "Created issue should have number"
|
||||
issue_number = created_issue['number']
|
||||
|
||||
try:
|
||||
# Step 2: Retrieve the created issue
|
||||
retrieved_issue = fetcher.fetch_issue(issue_number)
|
||||
|
||||
assert retrieved_issue.title == test_title, "Retrieved issue should have correct title"
|
||||
assert retrieved_issue.body == test_body, "Retrieved issue should have correct body"
|
||||
assert retrieved_issue.state == "open", "New issue should be open"
|
||||
|
||||
# Step 3: Update the issue
|
||||
updated_title = f"{test_title} - UPDATED"
|
||||
update_result = writer.update_issue_title(issue_number, updated_title)
|
||||
|
||||
assert 'number' in update_result, "Update should return issue data"
|
||||
assert update_result['title'] == updated_title, "Title should be updated"
|
||||
|
||||
# Step 4: Close the issue (cleanup)
|
||||
close_result = writer.close_issue(issue_number)
|
||||
assert close_result['state'] == 'closed', "Issue should be closed"
|
||||
|
||||
print(f"✅ Integration test successful - Issue #{issue_number} lifecycle completed")
|
||||
|
||||
except Exception as e:
|
||||
# If anything fails, try to clean up the test issue
|
||||
try:
|
||||
writer.close_issue(issue_number)
|
||||
print(f"⚠️ Test failed but cleaned up issue #{issue_number}")
|
||||
except:
|
||||
print(f"❌ Test failed and couldn't clean up issue #{issue_number}")
|
||||
raise e
|
||||
|
||||
def test_authentication_error_handling(self):
|
||||
"""Test proper handling of authentication errors."""
|
||||
config = self._get_test_config()
|
||||
creator = IssueCreator(config=config, auth_token="invalid-token")
|
||||
|
||||
with pytest.raises(IssueError, match="Failed to create issue"):
|
||||
creator.create_issue("Test", "Test body")
|
||||
|
||||
def test_api_endpoint_validation(self):
|
||||
"""Test that API endpoints are constructed correctly."""
|
||||
config = self._get_test_config()
|
||||
creator = IssueCreator(config=config)
|
||||
|
||||
expected_url = "http://92.205.130.254:32166/api/v1/repos/coulomb/markitect_project/issues"
|
||||
assert config.issues_api_url == expected_url, f"API URL should be {expected_url}"
|
||||
|
||||
def test_structured_enhancement_creation(self, auth_token):
|
||||
"""Test creating structured enhancement issue."""
|
||||
config = self._get_test_config()
|
||||
creator = IssueCreator(config=config, auth_token=auth_token)
|
||||
writer = IssueWriter(config=config, auth_token=auth_token)
|
||||
|
||||
test_title = f"Test Enhancement - {int(time.time())}"
|
||||
|
||||
created_issue = creator.create_enhancement_issue(
|
||||
title=test_title,
|
||||
use_case="Integration test for enhancement creation",
|
||||
technical_requirements="Should create structured issue body",
|
||||
acceptance_criteria=["Issue has structured format", "All sections present"],
|
||||
dependencies=["Integration test framework"],
|
||||
priority="Low"
|
||||
)
|
||||
|
||||
issue_number = created_issue['number']
|
||||
|
||||
try:
|
||||
# Verify structured content
|
||||
fetcher = IssueFetcher(config=config)
|
||||
retrieved_issue = fetcher.fetch_issue(issue_number)
|
||||
|
||||
body = retrieved_issue.body
|
||||
assert "UseCase:" in body, "Should contain UseCase section"
|
||||
assert "Technical Requirements:" in body, "Should contain Technical Requirements"
|
||||
assert "Acceptance Criteria:" in body, "Should contain Acceptance Criteria"
|
||||
assert "- [ ] Issue has structured format" in body, "Should contain checkbox items"
|
||||
assert "Dependencies:" in body, "Should contain Dependencies section"
|
||||
|
||||
print(f"✅ Structured enhancement test successful - Issue #{issue_number}")
|
||||
|
||||
finally:
|
||||
# Cleanup
|
||||
try:
|
||||
writer.close_issue(issue_number)
|
||||
except:
|
||||
pass # Best effort cleanup
|
||||
Reference in New Issue
Block a user