Initial upload: ScaffoldForge CLI tool with full codebase, tests, and CI/CD
This commit is contained in:
255
tests/unit/test_parsers.py
Normal file
255
tests/unit/test_parsers.py
Normal file
@@ -0,0 +1,255 @@
|
||||
"""Unit tests for the parsers module."""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock, patch, MagicMock
|
||||
|
||||
from scaffoldforge.parsers import IssueParser, IssueData, ChecklistItem
|
||||
|
||||
|
||||
class TestChecklistItem:
|
||||
"""Tests for ChecklistItem dataclass."""
|
||||
|
||||
def test_checklist_item_creation(self):
|
||||
"""Test creating a checklist item."""
|
||||
item = ChecklistItem(
|
||||
text="Implement feature",
|
||||
completed=False,
|
||||
line_number=5,
|
||||
category="Implementation"
|
||||
)
|
||||
assert item.text == "Implement feature"
|
||||
assert item.completed is False
|
||||
assert item.line_number == 5
|
||||
assert item.category == "Implementation"
|
||||
|
||||
def test_checklist_item_completed(self):
|
||||
"""Test completed checklist item."""
|
||||
item = ChecklistItem(
|
||||
text="Completed task",
|
||||
completed=True,
|
||||
line_number=10
|
||||
)
|
||||
assert item.completed is True
|
||||
|
||||
|
||||
class TestIssueData:
|
||||
"""Tests for IssueData dataclass."""
|
||||
|
||||
def test_issue_data_creation(self):
|
||||
"""Test creating issue data."""
|
||||
data = IssueData(
|
||||
number=123,
|
||||
title="Test Issue",
|
||||
body="Test body",
|
||||
body_html="<p>Test body</p>",
|
||||
labels=["bug", "priority"],
|
||||
state="open",
|
||||
url="https://github.com/user/repo/issues/123",
|
||||
repository="user/repo",
|
||||
author="testuser",
|
||||
created_at="2024-01-01T00:00:00",
|
||||
updated_at="2024-01-02T00:00:00"
|
||||
)
|
||||
assert data.number == 123
|
||||
assert data.title == "Test Issue"
|
||||
assert data.labels == ["bug", "priority"]
|
||||
|
||||
def test_get_todo_items(self):
|
||||
"""Test getting incomplete todo items."""
|
||||
checklist = [
|
||||
ChecklistItem(text="Task 1", completed=False),
|
||||
ChecklistItem(text="Task 2", completed=True),
|
||||
ChecklistItem(text="Task 3", completed=False),
|
||||
]
|
||||
data = IssueData(
|
||||
number=1, title="Test", body="", body_html="",
|
||||
labels=[], state="open", url="", repository="", author="",
|
||||
created_at="", updated_at="", checklist=checklist
|
||||
)
|
||||
todos = data.get_todo_items()
|
||||
assert len(todos) == 2
|
||||
assert "Task 1" in todos
|
||||
assert "Task 3" in todos
|
||||
assert "Task 2" not in todos
|
||||
|
||||
def test_get_completed_items(self):
|
||||
"""Test getting completed items."""
|
||||
checklist = [
|
||||
ChecklistItem(text="Task 1", completed=False),
|
||||
ChecklistItem(text="Task 2", completed=True),
|
||||
]
|
||||
data = IssueData(
|
||||
number=1, title="Test", body="", body_html="",
|
||||
labels=[], state="open", url="", repository="", author="",
|
||||
created_at="", updated_at="", checklist=checklist
|
||||
)
|
||||
completed = data.get_completed_items()
|
||||
assert len(completed) == 1
|
||||
assert "Task 2" in completed
|
||||
|
||||
def test_generate_todo_comments(self):
|
||||
"""Test generating TODO comments."""
|
||||
checklist = [
|
||||
ChecklistItem(text="Implement feature", completed=False),
|
||||
ChecklistItem(text="Write tests", completed=False),
|
||||
]
|
||||
data = IssueData(
|
||||
number=42, title="Test", body="", body_html="",
|
||||
labels=[], state="open", url="", repository="", author="",
|
||||
created_at="", updated_at="", checklist=checklist
|
||||
)
|
||||
comments = data.generate_todo_comments()
|
||||
assert "TODO #1: Implement feature" in comments
|
||||
assert "TODO #2: Write tests" in comments
|
||||
|
||||
|
||||
class TestIssueParser:
|
||||
"""Tests for IssueParser class."""
|
||||
|
||||
@patch('scaffoldforge.parsers.issue_parser.Github')
|
||||
def test_parser_initialization_without_token(self, mock_github):
|
||||
"""Test parser initialization without token."""
|
||||
parser = IssueParser()
|
||||
mock_github.assert_called_once()
|
||||
|
||||
@patch('scaffoldforge.parsers.issue_parser.Github')
|
||||
def test_parser_initialization_with_token(self, mock_github):
|
||||
"""Test parser initialization with token."""
|
||||
parser = IssueParser(token="test_token")
|
||||
mock_github.assert_called_once_with("test_token")
|
||||
|
||||
def test_parse_checklist_simple(self):
|
||||
"""Test parsing simple checklist items."""
|
||||
parser = IssueParser()
|
||||
body = """
|
||||
## Tasks
|
||||
- [x] Completed task
|
||||
- [ ] Pending task
|
||||
- [X] Also completed
|
||||
"""
|
||||
checklist = parser._parse_checklist(body)
|
||||
assert len(checklist) == 3
|
||||
assert checklist[0].text == "Completed task"
|
||||
assert checklist[0].completed is True
|
||||
assert checklist[1].text == "Pending task"
|
||||
assert checklist[1].completed is False
|
||||
|
||||
def test_parse_checklist_with_categories(self):
|
||||
"""Test parsing checklist with category headers."""
|
||||
parser = IssueParser()
|
||||
body = """
|
||||
## Implementation
|
||||
- [ ] Task 1
|
||||
- [ ] Task 2
|
||||
|
||||
## Testing
|
||||
- [ ] Test 1
|
||||
"""
|
||||
checklist = parser._parse_checklist(body)
|
||||
assert len(checklist) == 3
|
||||
assert checklist[0].category == "Implementation"
|
||||
assert checklist[2].category == "Testing"
|
||||
|
||||
def test_parse_requirements(self):
|
||||
"""Test parsing requirements section."""
|
||||
parser = IssueParser()
|
||||
body = """
|
||||
## Requirements
|
||||
- Must work
|
||||
- Must be fast
|
||||
- Must be secure
|
||||
"""
|
||||
requirements = parser._parse_requirements(body)
|
||||
assert len(requirements) == 3
|
||||
assert "Must work" in requirements
|
||||
|
||||
def test_parse_acceptance_criteria(self):
|
||||
"""Test parsing acceptance criteria."""
|
||||
parser = IssueParser()
|
||||
body = """
|
||||
## Acceptance Criteria
|
||||
- [x] Feature works
|
||||
- [ ] Tests pass
|
||||
"""
|
||||
criteria = parser._parse_acceptance_criteria(body)
|
||||
assert len(criteria) == 2
|
||||
assert "Feature works" in criteria
|
||||
|
||||
def test_parse_file_paths(self):
|
||||
"""Test parsing file paths from body."""
|
||||
parser = IssueParser()
|
||||
body = """
|
||||
Create a new file `src/main.py`
|
||||
Also need `utils.py`
|
||||
"""
|
||||
files = parser._parse_file_paths(body)
|
||||
assert len(files) >= 2
|
||||
|
||||
def test_detect_language_from_labels(self):
|
||||
"""Test language detection from labels."""
|
||||
parser = IssueParser()
|
||||
issue_data = IssueData(
|
||||
number=1, title="Test", body="", body_html="",
|
||||
labels=["python", "enhancement"], state="open", url="",
|
||||
repository="", author="", created_at="", updated_at=""
|
||||
)
|
||||
lang = parser.detect_language(issue_data)
|
||||
assert lang == "python"
|
||||
|
||||
def test_detect_language_from_body(self):
|
||||
"""Test language detection from body content."""
|
||||
parser = IssueParser()
|
||||
issue_data = IssueData(
|
||||
number=1, title="Test", body="This is a Go project",
|
||||
body_html="", labels=[], state="open", url="",
|
||||
repository="", author="", created_at="", updated_at=""
|
||||
)
|
||||
lang = parser.detect_language(issue_data)
|
||||
assert lang == "go"
|
||||
|
||||
def test_detect_language_unknown(self):
|
||||
"""Test language detection when unknown."""
|
||||
parser = IssueParser()
|
||||
issue_data = IssueData(
|
||||
number=1, title="Test", body="No language mentioned",
|
||||
body_html="", labels=[], state="open", url="",
|
||||
repository="", author="", created_at="", updated_at=""
|
||||
)
|
||||
lang = parser.detect_language(issue_data)
|
||||
assert lang is None
|
||||
|
||||
def test_detect_project_type_cli(self):
|
||||
"""Test CLI project type detection."""
|
||||
parser = IssueParser()
|
||||
issue_data = IssueData(
|
||||
number=1, title="Create a CLI tool",
|
||||
body="Need to build a command line interface",
|
||||
body_html="", labels=[], state="open", url="",
|
||||
repository="", author="", created_at="", updated_at=""
|
||||
)
|
||||
proj_type = parser.detect_project_type(issue_data)
|
||||
assert proj_type == "cli"
|
||||
|
||||
def test_detect_project_type_api(self):
|
||||
"""Test API project type detection."""
|
||||
parser = IssueParser()
|
||||
issue_data = IssueData(
|
||||
number=1, title="Create REST API",
|
||||
body="Build an API endpoint",
|
||||
body_html="", labels=[], state="open", url="",
|
||||
repository="", author="", created_at="", updated_at=""
|
||||
)
|
||||
proj_type = parser.detect_project_type(issue_data)
|
||||
assert proj_type == "api"
|
||||
|
||||
def test_empty_body_handling(self):
|
||||
"""Test handling of empty body."""
|
||||
parser = IssueParser()
|
||||
checklist = parser._parse_checklist("")
|
||||
assert len(checklist) == 0
|
||||
|
||||
requirements = parser._parse_requirements("")
|
||||
assert len(requirements) == 0
|
||||
|
||||
files = parser._parse_file_paths("")
|
||||
assert len(files) == 0
|
||||
Reference in New Issue
Block a user