feat: reorganize tests by capability with separate test targets
Some checks failed
Test Suite / unit-tests (3.11) (push) Has been cancelled
Test Suite / unit-tests (3.12) (push) Has been cancelled
Test Suite / integration-tests (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / performance-tests (push) Has been cancelled
Test Suite / code-quality (push) Has been cancelled
Test Suite / security-scan (push) Has been cancelled
Test Suite / test-summary (push) Has been cancelled
Some checks failed
Test Suite / unit-tests (3.11) (push) Has been cancelled
Test Suite / unit-tests (3.12) (push) Has been cancelled
Test Suite / integration-tests (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / performance-tests (push) Has been cancelled
Test Suite / code-quality (push) Has been cancelled
Test Suite / security-scan (push) Has been cancelled
Test Suite / test-summary (push) Has been cancelled
Separate capability-specific tests from core system tests to establish clear test organization and separation of concerns. ## Test Reorganization: - **markitect-content tests**: Moved 6 tests to capabilities/markitect-content/tests/ - **markitect-finance tests**: Moved 7 tests to markitect/finance/tests/ - **markitect-query tests**: Moved 1 test to markitect/query_paradigms/tests/ - **markitect-graphql tests**: Moved 2 tests to markitect/graphql/tests/ - **markitect-plugins tests**: Moved 2 tests to markitect/plugins/tests/ ## Makefile Updates: - **make test**: Excludes capability tests, runs only core system tests - **make test-capabilities**: Runs all capability tests - **make test-capability-***: Individual capability test targets - Updated all test targets (test-red, test-green, test-ultra-fast, test-perf) - Added capability test targets to help documentation ## Benefits: - Clear separation between core system tests and capability-specific tests - Faster core test execution (capability tests not run by default) - Individual capability testing for focused development - Supports future capability extraction workflow - Maintains capability test independence Test verification: - Core tests: 1291 tests (capability tests excluded) - Finance capability: 143 tests working independently - Content capability: 79 tests working independently 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
619
markitect/graphql/tests/test_issue_9_graphql_interface.py
Normal file
619
markitect/graphql/tests/test_issue_9_graphql_interface.py
Normal file
@@ -0,0 +1,619 @@
|
||||
"""
|
||||
Comprehensive tests for GraphQL interface (Issue #9).
|
||||
|
||||
Tests all aspects of the GraphQL read interface including:
|
||||
- Schema definition and validation
|
||||
- Resolver functionality
|
||||
- Server endpoints
|
||||
- CLI integration
|
||||
- Error handling
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import json
|
||||
import sqlite3
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock, patch, MagicMock
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
from markitect.graphql.schema import schema, MarkdownFile, Schema as SchemaType, AST, DatabaseStats
|
||||
from markitect.graphql.resolvers import Query, MarkiTectResolver, get_default_database_path
|
||||
from markitect.graphql.server import GraphQLServer, GraphQLClient
|
||||
from markitect.database import DatabaseManager
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def temp_db_path():
|
||||
"""Create temporary database for testing."""
|
||||
with tempfile.NamedTemporaryFile(suffix='.db', delete=False) as f:
|
||||
db_path = f.name
|
||||
|
||||
# Initialize database with test data
|
||||
db_manager = DatabaseManager(db_path)
|
||||
db_manager.initialize_database()
|
||||
|
||||
# Add sample data
|
||||
conn = sqlite3.connect(db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Sample markdown file
|
||||
cursor.execute("""
|
||||
INSERT INTO markdown_files (filename, content, front_matter, created_at)
|
||||
VALUES (?, ?, ?, ?)
|
||||
""", (
|
||||
'test.md',
|
||||
'# Test Document\n\nThis is a test document with [a link](http://example.com).',
|
||||
'{"title": "Test Document", "author": "Test Author"}',
|
||||
datetime.now().isoformat()
|
||||
))
|
||||
|
||||
# Sample schema
|
||||
cursor.execute("""
|
||||
INSERT INTO schemas (filename, title, description, schema_content, created_at)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
""", (
|
||||
'test-schema.json',
|
||||
'Test Schema',
|
||||
'A test schema for testing',
|
||||
'{"type": "object", "properties": {"name": {"type": "string"}}}',
|
||||
datetime.now().isoformat()
|
||||
))
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
yield db_path
|
||||
|
||||
# Cleanup
|
||||
os.unlink(db_path)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def graphql_resolver(temp_db_path):
|
||||
"""Create GraphQL resolver with test database."""
|
||||
return MarkiTectResolver(temp_db_path)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def graphql_query(temp_db_path):
|
||||
"""Create GraphQL Query instance with test database."""
|
||||
with patch('markitect.graphql.resolvers.get_default_database_path', return_value=temp_db_path):
|
||||
return Query()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def flask_app(temp_db_path):
|
||||
"""Create Flask app for testing GraphQL server."""
|
||||
server = GraphQLServer(db_path=temp_db_path, enable_cors=True)
|
||||
app = server.create_app()
|
||||
app.config['TESTING'] = True
|
||||
return app
|
||||
|
||||
|
||||
class TestGraphQLSchema:
|
||||
"""Test GraphQL schema definition and validation."""
|
||||
|
||||
def test_schema_is_valid(self):
|
||||
"""Test that the GraphQL schema is valid."""
|
||||
assert schema is not None
|
||||
assert hasattr(schema, 'execute')
|
||||
|
||||
def test_schema_has_required_types(self):
|
||||
"""Test that schema contains all required types."""
|
||||
schema_str = str(schema)
|
||||
|
||||
# Check for main types
|
||||
assert 'MarkdownFile' in schema_str
|
||||
assert 'Schema' in schema_str
|
||||
assert 'AST' in schema_str
|
||||
assert 'DatabaseStats' in schema_str
|
||||
assert 'SearchResult' in schema_str
|
||||
|
||||
def test_query_type_fields(self):
|
||||
"""Test that Query type has all required fields."""
|
||||
schema_str = str(schema)
|
||||
|
||||
# Check for query fields
|
||||
assert 'markdownFile' in schema_str
|
||||
assert 'markdownFiles' in schema_str
|
||||
assert 'schema' in schema_str
|
||||
assert 'schemas' in schema_str
|
||||
assert 'ast' in schema_str
|
||||
assert 'search' in schema_str
|
||||
assert 'databaseStats' in schema_str
|
||||
assert 'astQuery' in schema_str
|
||||
|
||||
|
||||
class TestGraphQLResolvers:
|
||||
"""Test GraphQL resolver functionality."""
|
||||
|
||||
def test_resolver_initialization(self, temp_db_path):
|
||||
"""Test resolver initializes correctly."""
|
||||
resolver = MarkiTectResolver(temp_db_path)
|
||||
|
||||
assert resolver.db_path == temp_db_path
|
||||
assert resolver.db_manager is not None
|
||||
assert resolver.ast_service is not None
|
||||
|
||||
def test_get_connection(self, graphql_resolver):
|
||||
"""Test database connection method."""
|
||||
conn = graphql_resolver.get_connection()
|
||||
|
||||
assert conn is not None
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT 1")
|
||||
result = cursor.fetchone()
|
||||
assert result[0] == 1
|
||||
conn.close()
|
||||
|
||||
def test_row_to_dict(self, graphql_resolver):
|
||||
"""Test row to dictionary conversion."""
|
||||
conn = graphql_resolver.get_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT 1 as test_col")
|
||||
row = cursor.fetchone()
|
||||
|
||||
result = graphql_resolver.row_to_dict(cursor, row)
|
||||
assert result == {'test_col': 1}
|
||||
conn.close()
|
||||
|
||||
def test_resolve_markdown_file_by_id(self, graphql_query):
|
||||
"""Test resolving markdown file by ID."""
|
||||
result = graphql_query.resolve_markdown_file(None, id=1)
|
||||
|
||||
assert result is not None
|
||||
assert isinstance(result, MarkdownFile)
|
||||
assert result.filename == 'test.md'
|
||||
assert 'Test Document' in result.content
|
||||
|
||||
def test_resolve_markdown_file_by_filename(self, graphql_query):
|
||||
"""Test resolving markdown file by filename."""
|
||||
result = graphql_query.resolve_markdown_file(None, filename='test.md')
|
||||
|
||||
assert result is not None
|
||||
assert isinstance(result, MarkdownFile)
|
||||
assert result.id == 1
|
||||
|
||||
def test_resolve_markdown_file_not_found(self, graphql_query):
|
||||
"""Test resolving non-existent markdown file."""
|
||||
result = graphql_query.resolve_markdown_file(None, id=999)
|
||||
assert result is None
|
||||
|
||||
result = graphql_query.resolve_markdown_file(None, filename='nonexistent.md')
|
||||
assert result is None
|
||||
|
||||
def test_resolve_schema_by_id(self, graphql_query):
|
||||
"""Test resolving schema by ID."""
|
||||
result = graphql_query.resolve_schema(None, id=1)
|
||||
|
||||
assert result is not None
|
||||
assert isinstance(result, SchemaType)
|
||||
assert result.title == 'Test Schema'
|
||||
|
||||
def test_resolve_markdown_files_list(self, graphql_query):
|
||||
"""Test resolving list of markdown files."""
|
||||
results = graphql_query.resolve_markdown_files(None, limit=10, offset=0)
|
||||
|
||||
assert isinstance(results, list)
|
||||
assert len(results) >= 1
|
||||
assert all(isinstance(f, MarkdownFile) for f in results)
|
||||
|
||||
def test_resolve_schemas_list(self, graphql_query):
|
||||
"""Test resolving list of schemas."""
|
||||
results = graphql_query.resolve_schemas(None, limit=10, offset=0)
|
||||
|
||||
assert isinstance(results, list)
|
||||
assert len(results) >= 1
|
||||
assert all(isinstance(s, SchemaType) for s in results)
|
||||
|
||||
def test_resolve_search_files(self, graphql_query):
|
||||
"""Test search functionality for files."""
|
||||
results = graphql_query.resolve_search(None, query="Test", type="file", limit=10)
|
||||
|
||||
assert isinstance(results, list)
|
||||
assert len(results) >= 1
|
||||
assert all(hasattr(r, 'type') and hasattr(r, 'score') for r in results)
|
||||
|
||||
def test_resolve_database_stats(self, graphql_query):
|
||||
"""Test database statistics resolver."""
|
||||
result = graphql_query.resolve_database_stats(None)
|
||||
|
||||
assert result is not None
|
||||
assert isinstance(result, DatabaseStats)
|
||||
assert result.total_files >= 1
|
||||
assert result.total_schemas >= 1
|
||||
assert result.total_size_bytes > 0
|
||||
|
||||
@patch('markitect.graphql.resolvers.Path.exists')
|
||||
def test_resolve_ast_file_not_found(self, mock_exists, graphql_query):
|
||||
"""Test AST resolution when file doesn't exist."""
|
||||
mock_exists.return_value = False
|
||||
|
||||
result = graphql_query.resolve_ast(None, filename='nonexistent.md')
|
||||
assert result is None
|
||||
|
||||
|
||||
class TestGraphQLServer:
|
||||
"""Test GraphQL server functionality."""
|
||||
|
||||
def test_server_initialization(self, temp_db_path):
|
||||
"""Test server initializes correctly."""
|
||||
server = GraphQLServer(db_path=temp_db_path, enable_cors=True)
|
||||
|
||||
assert server.db_path == temp_db_path
|
||||
assert server.enable_cors is True
|
||||
assert server.app is None
|
||||
|
||||
def test_server_initialization_without_flask(self):
|
||||
"""Test server initialization when Flask is not available."""
|
||||
with patch('markitect.graphql.server.FLASK_AVAILABLE', False):
|
||||
with pytest.raises(ImportError, match="Flask is required"):
|
||||
GraphQLServer()
|
||||
|
||||
def test_create_app(self, temp_db_path):
|
||||
"""Test Flask app creation."""
|
||||
server = GraphQLServer(db_path=temp_db_path)
|
||||
app = server.create_app()
|
||||
|
||||
assert app is not None
|
||||
assert server.app is app
|
||||
|
||||
def test_graphql_endpoint_post(self, flask_app):
|
||||
"""Test GraphQL POST endpoint."""
|
||||
with flask_app.test_client() as client:
|
||||
query = '{ databaseStats { totalFiles } }'
|
||||
response = client.post('/graphql',
|
||||
json={'query': query},
|
||||
content_type='application/json')
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.get_json()
|
||||
assert 'data' in data
|
||||
assert 'databaseStats' in data['data']
|
||||
|
||||
def test_graphql_endpoint_invalid_json(self, flask_app):
|
||||
"""Test GraphQL endpoint with invalid JSON."""
|
||||
with flask_app.test_client() as client:
|
||||
response = client.post('/graphql',
|
||||
data='invalid json',
|
||||
content_type='application/json')
|
||||
|
||||
# Flask returns 500 for malformed JSON, which is reasonable
|
||||
assert response.status_code in [400, 500]
|
||||
|
||||
def test_graphql_endpoint_no_query(self, flask_app):
|
||||
"""Test GraphQL endpoint without query."""
|
||||
with flask_app.test_client() as client:
|
||||
response = client.post('/graphql',
|
||||
json={},
|
||||
content_type='application/json')
|
||||
|
||||
assert response.status_code == 400
|
||||
data = response.get_json()
|
||||
assert 'error' in data
|
||||
|
||||
def test_graphql_playground(self, flask_app):
|
||||
"""Test GraphQL playground endpoint."""
|
||||
with flask_app.test_client() as client:
|
||||
response = client.get('/graphql')
|
||||
|
||||
assert response.status_code == 200
|
||||
assert 'GraphQL Playground' in response.get_data(as_text=True)
|
||||
|
||||
def test_schema_endpoint(self, flask_app):
|
||||
"""Test schema introspection endpoint."""
|
||||
with flask_app.test_client() as client:
|
||||
response = client.get('/schema')
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.get_json()
|
||||
assert 'schema' in data
|
||||
|
||||
def test_health_check_healthy(self, flask_app):
|
||||
"""Test health check endpoint when healthy."""
|
||||
with flask_app.test_client() as client:
|
||||
response = client.get('/health')
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.get_json()
|
||||
assert data['status'] == 'healthy'
|
||||
assert data['database'] == 'connected'
|
||||
|
||||
def test_health_check_unhealthy(self, temp_db_path):
|
||||
"""Test health check when database is unavailable."""
|
||||
# Use non-existent database path
|
||||
server = GraphQLServer(db_path='/nonexistent/path.db')
|
||||
app = server.create_app()
|
||||
|
||||
with app.test_client() as client:
|
||||
response = client.get('/health')
|
||||
|
||||
assert response.status_code == 500
|
||||
data = response.get_json()
|
||||
assert data['status'] == 'unhealthy'
|
||||
|
||||
|
||||
class TestGraphQLClient:
|
||||
"""Test GraphQL client functionality."""
|
||||
|
||||
def test_client_initialization(self):
|
||||
"""Test client initializes correctly."""
|
||||
client = GraphQLClient("http://localhost:5000/graphql")
|
||||
assert client.endpoint == "http://localhost:5000/graphql"
|
||||
|
||||
def test_client_default_endpoint(self):
|
||||
"""Test client uses default endpoint."""
|
||||
client = GraphQLClient()
|
||||
assert client.endpoint == "http://localhost:5000/graphql"
|
||||
|
||||
@patch('requests.post')
|
||||
def test_client_execute_query(self, mock_post):
|
||||
"""Test client query execution."""
|
||||
# Mock response
|
||||
mock_response = Mock()
|
||||
mock_response.json.return_value = {
|
||||
'data': {'databaseStats': {'totalFiles': 5}}
|
||||
}
|
||||
mock_post.return_value = mock_response
|
||||
|
||||
client = GraphQLClient()
|
||||
result = client.execute('{ databaseStats { totalFiles } }')
|
||||
|
||||
assert result['data']['databaseStats']['totalFiles'] == 5
|
||||
mock_post.assert_called_once()
|
||||
|
||||
def test_client_execute_local(self, temp_db_path):
|
||||
"""Test client local query execution."""
|
||||
with patch('markitect.graphql.resolvers.get_default_database_path', return_value=temp_db_path):
|
||||
client = GraphQLClient()
|
||||
result = client.execute_local('{ databaseStats { totalFiles } }', context={'db_path': temp_db_path})
|
||||
|
||||
assert result is not None
|
||||
assert 'data' in result
|
||||
# The databaseStats resolver might return None if db is empty, so let's be more flexible
|
||||
if result['data']['databaseStats'] is not None:
|
||||
assert result['data']['databaseStats']['totalFiles'] >= 0
|
||||
|
||||
def test_client_execute_without_requests(self):
|
||||
"""Test client execution when requests is not available."""
|
||||
import builtins
|
||||
original_import = builtins.__import__
|
||||
|
||||
def mock_import(name, *args, **kwargs):
|
||||
if name == 'requests':
|
||||
raise ImportError("No module named 'requests'")
|
||||
return original_import(name, *args, **kwargs)
|
||||
|
||||
with patch('builtins.__import__', side_effect=mock_import):
|
||||
client = GraphQLClient()
|
||||
|
||||
with pytest.raises(ImportError, match="requests is required"):
|
||||
client.execute('{ databaseStats { totalFiles } }')
|
||||
|
||||
|
||||
class TestGraphQLQueries:
|
||||
"""Test actual GraphQL query execution."""
|
||||
|
||||
def test_simple_database_stats_query(self, temp_db_path):
|
||||
"""Test simple database stats query."""
|
||||
with patch('markitect.graphql.resolvers.get_default_database_path', return_value=temp_db_path):
|
||||
query = """
|
||||
{
|
||||
databaseStats {
|
||||
totalFiles
|
||||
totalSchemas
|
||||
totalSizeBytes
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
result = schema.execute(query, context={'db_path': temp_db_path})
|
||||
|
||||
assert result.errors is None
|
||||
assert result.data is not None
|
||||
assert 'databaseStats' in result.data
|
||||
if result.data['databaseStats'] is not None:
|
||||
assert result.data['databaseStats']['totalFiles'] >= 1
|
||||
assert result.data['databaseStats']['totalSchemas'] >= 1
|
||||
|
||||
def test_markdown_file_query_with_computed_fields(self, temp_db_path):
|
||||
"""Test markdown file query with computed fields."""
|
||||
with patch('markitect.graphql.resolvers.get_default_database_path', return_value=temp_db_path):
|
||||
query = """
|
||||
{
|
||||
markdownFile(id: 1) {
|
||||
id
|
||||
filename
|
||||
content
|
||||
wordCount
|
||||
lineCount
|
||||
hasFrontMatter
|
||||
frontMatter {
|
||||
key
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
result = schema.execute(query, context={'db_path': temp_db_path})
|
||||
|
||||
assert result.errors is None
|
||||
assert result.data is not None
|
||||
data = result.data['markdownFile']
|
||||
if data is not None:
|
||||
assert data['id'] == 1
|
||||
assert data['filename'] == 'test.md'
|
||||
assert data['wordCount'] > 0
|
||||
assert data['lineCount'] > 0
|
||||
assert data['hasFrontMatter'] is True
|
||||
assert len(data['frontMatter']) > 0
|
||||
|
||||
def test_search_query(self, temp_db_path):
|
||||
"""Test search functionality."""
|
||||
with patch('markitect.graphql.resolvers.get_default_database_path', return_value=temp_db_path):
|
||||
query = """
|
||||
{
|
||||
search(query: "Test", type: "all", limit: 10) {
|
||||
type
|
||||
score
|
||||
file {
|
||||
filename
|
||||
}
|
||||
schema {
|
||||
title
|
||||
}
|
||||
highlight
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
result = schema.execute(query, context={'db_path': temp_db_path})
|
||||
|
||||
assert result.errors is None
|
||||
assert result.data is not None
|
||||
if result.data['search'] is not None:
|
||||
assert len(result.data['search']) >= 0
|
||||
|
||||
def test_pagination_query(self, temp_db_path):
|
||||
"""Test pagination in list queries."""
|
||||
with patch('markitect.graphql.resolvers.get_default_database_path', return_value=temp_db_path):
|
||||
query = """
|
||||
{
|
||||
markdownFiles(limit: 1, offset: 0) {
|
||||
id
|
||||
filename
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
result = schema.execute(query, context={'db_path': temp_db_path})
|
||||
|
||||
assert result.errors is None
|
||||
assert result.data is not None
|
||||
if result.data['markdownFiles'] is not None:
|
||||
assert len(result.data['markdownFiles']) <= 1
|
||||
|
||||
|
||||
@pytest.mark.e2e
|
||||
class TestGraphQLCLIIntegration:
|
||||
"""Test GraphQL CLI command integration."""
|
||||
|
||||
def test_graphql_schema_command(self, isolated_environment):
|
||||
"""Test graphql-schema CLI command."""
|
||||
result = subprocess.run(
|
||||
[sys.executable, "-m", "markitect.cli", "graphql-schema", "--local"],
|
||||
env=isolated_environment,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=Path.cwd()
|
||||
)
|
||||
|
||||
assert result.returncode == 0
|
||||
assert "type Query" in result.stdout
|
||||
|
||||
def test_graphql_query_command(self, isolated_environment):
|
||||
"""Test graphql-query CLI command."""
|
||||
query = "{ databaseStats { totalFiles } }"
|
||||
|
||||
result = subprocess.run(
|
||||
[sys.executable, "-m", "markitect.cli", "graphql-query", query, "--local"],
|
||||
env=isolated_environment,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=Path.cwd()
|
||||
)
|
||||
|
||||
assert result.returncode == 0
|
||||
# The database might be empty in test environment, so check for JSON structure
|
||||
assert "databaseStats" in result.stdout
|
||||
|
||||
def test_graphql_examples_command(self, isolated_environment):
|
||||
"""Test graphql-examples CLI command."""
|
||||
result = subprocess.run(
|
||||
[sys.executable, "-m", "markitect.cli", "graphql-examples"],
|
||||
env=isolated_environment,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=Path.cwd()
|
||||
)
|
||||
|
||||
assert result.returncode == 0
|
||||
assert "GraphQL Query Examples" in result.stdout
|
||||
assert "databaseStats" in result.stdout
|
||||
|
||||
@patch('markitect.graphql.server.GraphQLServer')
|
||||
def test_graphql_serve_command(self, mock_server_class, isolated_environment):
|
||||
"""Test graphql-serve CLI command."""
|
||||
mock_server = Mock()
|
||||
mock_server_class.return_value = mock_server
|
||||
|
||||
# We can't actually start the server in tests, so we just test command parsing
|
||||
result = subprocess.run(
|
||||
[sys.executable, "-m", "markitect.cli", "graphql-serve", "--help"],
|
||||
env=isolated_environment,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=Path.cwd()
|
||||
)
|
||||
|
||||
assert result.returncode == 0
|
||||
assert "Start GraphQL server" in result.stdout
|
||||
|
||||
|
||||
class TestErrorHandling:
|
||||
"""Test error handling in GraphQL interface."""
|
||||
|
||||
def test_invalid_query_syntax(self, temp_db_path):
|
||||
"""Test handling of invalid GraphQL syntax."""
|
||||
with patch('markitect.graphql.resolvers.get_default_database_path', return_value=temp_db_path):
|
||||
query = "{ invalidSyntax }"
|
||||
|
||||
result = schema.execute(query)
|
||||
|
||||
assert result.errors is not None
|
||||
assert len(result.errors) > 0
|
||||
|
||||
def test_nonexistent_field_query(self, temp_db_path):
|
||||
"""Test querying nonexistent fields."""
|
||||
with patch('markitect.graphql.resolvers.get_default_database_path', return_value=temp_db_path):
|
||||
query = "{ nonexistentField }"
|
||||
|
||||
result = schema.execute(query)
|
||||
|
||||
assert result.errors is not None
|
||||
|
||||
def test_resolver_database_error(self, temp_db_path):
|
||||
"""Test resolver behavior when database is corrupted."""
|
||||
# Corrupt the database file
|
||||
with open(temp_db_path, 'w') as f:
|
||||
f.write("corrupted data")
|
||||
|
||||
with patch('markitect.graphql.resolvers.get_default_database_path', return_value=temp_db_path):
|
||||
query = "{ databaseStats { totalFiles } }"
|
||||
|
||||
result = schema.execute(query, context={'db_path': temp_db_path})
|
||||
|
||||
# Should handle database errors gracefully - either with errors or None data
|
||||
assert result.errors is not None or result.data['databaseStats'] is None
|
||||
|
||||
|
||||
class TestUtilityFunctions:
|
||||
"""Test utility functions in GraphQL module."""
|
||||
|
||||
def test_get_default_database_path_with_env(self):
|
||||
"""Test get_default_database_path with environment variable."""
|
||||
with patch.dict(os.environ, {'MARKITECT_DB': '/custom/path.db'}):
|
||||
path = get_default_database_path()
|
||||
assert path == '/custom/path.db'
|
||||
|
||||
def test_get_default_database_path_default(self):
|
||||
"""Test get_default_database_path with default location."""
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
path = get_default_database_path()
|
||||
assert path.endswith('markitect.db')
|
||||
assert '.markitect' in path
|
||||
Reference in New Issue
Block a user