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>
163 lines
6.6 KiB
Python
163 lines
6.6 KiB
Python
"""
|
|
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 |