"""Tests for the indexers.""" import pytest from src.indexer.openapi import OpenAPIIndexer from src.indexer.readme import READMEIndexer from src.indexer.code import CodeIndexer from src.models.document import SourceType class TestOpenAPIIndexer: """Tests for the OpenAPI indexer.""" @pytest.fixture def sample_openapi_yaml(self): """Create a sample OpenAPI spec for testing.""" content = """ openapi: "3.0.0" info: title: Test API version: "1.0.0" description: A test API for unit testing paths: /users: get: summary: List users description: Get a list of all users operationId: listUsers tags: - users parameters: - name: limit in: query schema: type: integer description: Maximum number of users responses: '200': description: Successful response content: application/json: schema: type: array items: type: object post: summary: Create user operationId: createUser tags: - users requestBody: required: true content: application/json: schema: type: object properties: name: type: string email: type: string responses: '201': description: User created /users/{userId}: get: summary: Get user operationId: getUser parameters: - name: userId in: path required: true schema: type: integer components: schemas: User: type: object properties: id: type: integer name: type: string required: - id - name """ return content def test_index_openapi_yaml(self, tmp_path, sample_openapi_yaml): """Test indexing a YAML OpenAPI spec.""" file_path = tmp_path / "openapi.yaml" file_path.write_text(sample_openapi_yaml) indexer = OpenAPIIndexer() documents = indexer.index(tmp_path, recursive=False) assert len(documents) > 0 assert all(doc.source_type == SourceType.OPENAPI for doc in documents) titles = [doc.title for doc in documents] assert any("Test API" in title for title in titles) assert any("GET" in title or "/users" in title for title in titles) def test_index_openapi_json(self, tmp_path): """Test indexing a JSON OpenAPI spec.""" content = """{ "openapi": "3.0.0", "info": { "title": "JSON API", "version": "1.0.0" }, "paths": {} }""" file_path = tmp_path / "openapi.json" file_path.write_text(content) indexer = OpenAPIIndexer() documents = indexer.index(tmp_path, recursive=False) assert len(documents) > 0 def test_unsupported_file(self, tmp_path): """Test that unsupported files are ignored.""" file_path = tmp_path / "test.txt" file_path.write_text("This is not an OpenAPI spec") indexer = OpenAPIIndexer() documents = indexer.index(tmp_path, recursive=False) assert len(documents) == 0 class TestREADMEIndexer: """Tests for the README indexer.""" @pytest.fixture def sample_readme(self): """Create a sample README for testing.""" content = """# Project Documentation This is a sample project for testing the README indexer. ## Installation To install the project, run: ```bash pip install myproject ``` ## Usage The main function can be called as follows: ```python from myproject import main main() ``` ## Configuration You can configure the project using environment variables: - `API_KEY`: Your API key - `DEBUG`: Enable debug mode ## API Reference ### Endpoints - `GET /users` - List all users - `POST /users` - Create a new user """ return content def test_index_readme(self, tmp_path, sample_readme): """Test indexing a README file.""" file_path = tmp_path / "README.md" file_path.write_text(sample_readme) indexer = READMEIndexer() documents = indexer.index(tmp_path, recursive=False) assert len(documents) > 0 assert all(doc.source_type == SourceType.README for doc in documents) titles = [doc.title for doc in documents] assert any("Project Documentation" in title for title in titles) def test_section_extraction(self, tmp_path, sample_readme): """Test that sections are properly extracted.""" file_path = tmp_path / "README.md" file_path.write_text(sample_readme) indexer = READMEIndexer() documents = indexer.index(tmp_path, recursive=False) assert len(documents) >= 1 content = documents[0].content assert "Installation" in content assert "Usage" in content def test_unsupported_extension(self, tmp_path): """Test that unsupported extensions are ignored.""" file_path = tmp_path / "readme.xyz" file_path.write_text("# Readme") indexer = READMEIndexer() documents = indexer.index(tmp_path, recursive=False) assert len(documents) == 0 class TestCodeIndexer: """Tests for the code indexer.""" @pytest.fixture def sample_python(self): """Create a sample Python file for testing.""" content = '''"""Sample module for testing.""" def add_numbers(a, b): """Add two numbers together. Args: a: First number b: Second number Returns: The sum of a and b """ return a + b class Calculator: """A simple calculator class. This class provides basic arithmetic operations. """ def __init__(self, initial_value=0): """Initialize the calculator. Args: initial_value: Starting value """ self.value = initial_value def add(self, number): """Add a number to the current value. Args: number: Number to add """ self.value += number ''' return content def test_index_python(self, tmp_path, sample_python): """Test indexing a Python file.""" file_path = tmp_path / "sample.py" file_path.write_text(sample_python) indexer = CodeIndexer() documents = indexer.index(tmp_path, recursive=False) assert len(documents) > 0 assert all(doc.source_type == SourceType.CODE for doc in documents) titles = [doc.title for doc in documents] assert any("add_numbers" in title for title in titles) assert any("Calculator" in title for title in titles) def test_function_docstring(self, tmp_path, sample_python): """Test that function docstrings are extracted.""" file_path = tmp_path / "sample.py" file_path.write_text(sample_python) indexer = CodeIndexer() documents = indexer.index(tmp_path, recursive=False) add_doc = [d for d in documents if "add_numbers" in d.title] if add_doc: assert "Add two numbers" in add_doc[0].content def test_class_docstring(self, tmp_path, sample_python): """Test that class docstrings are extracted.""" file_path = tmp_path / "sample.py" file_path.write_text(sample_python) indexer = CodeIndexer() documents = indexer.index(tmp_path, recursive=False) calc_doc = [d for d in documents if "Calculator" in d.title] if calc_doc: assert "simple calculator" in calc_doc[0].content.lower() def test_jsdoc_extraction(self, tmp_path): """Test JSDoc comment extraction.""" content = ''' /** * Multiplies two numbers. * @param {number} a - First number * @param {number} b - Second number * @returns {number} The product of a and b */ function multiply(a, b) { return a * b; } /** * A Greeter class. * @class */ class Greeter { /** * Create a greeter. * @param {string} name - Name to greet */ constructor(name) { this.name = name; } } ''' file_path = tmp_path / "sample.js" file_path.write_text(content) indexer = CodeIndexer() documents = indexer.index(tmp_path, recursive=False) func_doc = [d for d in documents if "multiply" in d.title] if func_doc: assert "Multiplies two numbers" in func_doc[0].content assert "number" in func_doc[0].content