diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..360730e --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,507 @@ +"""Pytest configuration and fixtures for codechunk tests.""" + +import tempfile +from collections.abc import Generator +from pathlib import Path + +import pytest + + +@pytest.fixture +def temp_project_dir() -> Generator[Path, None, None]: + """Create a temporary directory for testing.""" + with tempfile.TemporaryDirectory() as tmp_dir: + yield Path(tmp_dir) + + +@pytest.fixture +def sample_python_code(): + return ''' +"""Sample module for testing.""" + +import os +import json +from typing import List, Dict + + +class DataProcessor: + """A class for processing data.""" + + def __init__(self, config: Dict[str, str]): + self.config = config + self.cache = {} + + def process(self, items: List[str]) -> List[Dict]: + """Process a list of items. + + Args: + items: List of strings to process + + Returns: + List of processed dictionaries + """ + results = [] + for item in items: + if item in self.cache: + results.append(self.cache[item]) + else: + processed = self._process_single(item) + self.cache[item] = processed + results.append(processed) + return results + + def _process_single(self, item: str) -> Dict: + """Process a single item.""" + return {"item": item, "length": len(item)} + + +def main(): + """Main entry point.""" + processor = DataProcessor({"debug": "true"}) + result = processor.process(["hello", "world"]) + print(json.dumps(result)) + + +if __name__ == "__main__": + main() +''' + + +@pytest.fixture +def sample_javascript_code(): + return ''' +import { useState, useEffect } from 'react'; +import api from './api'; + +class DataManager { + constructor(config) { + this.config = config; + this.cache = new Map(); + } + + async fetchData(url) { + if (this.cache.has(url)) { + return this.cache.get(url); + } + + const response = await fetch(url); + const data = await response.json(); + this.cache.set(url, data); + return data; + } + + clearCache() { + this.cache.clear(); + } +} + +export function useCustomHook(initialValue) { + const [value, setValue] = useState(initialValue); + + useEffect(() => { + console.log('Value changed:', value); + }, [value]); + + return [value, setValue]; +} + +export default DataManager; +''' + + +@pytest.fixture +def sample_go_code(): + return '''package main + +import ( + "fmt" + "os" +) + +type Config struct { + Host string + Port int +} + +func (c *Config) Load() error { + return nil +} + +func NewProcessor(config Config) *Processor { + return &Processor{config: config} +} + +type Processor struct { + config Config +} + +func (p *Processor) Process(data string) error { + fmt.Println("Processing:", data) + return nil +} + +func main() { + config := Config{Host: "localhost", Port: 8080} + processor := NewProcessor(config) + err := processor.Process("test") + if err != nil { + os.Exit(1) + } +} +''' + + +@pytest.fixture +def sample_rust_code(): + return '''use std::collections::HashMap; + +pub struct Config { + host: String, + port: u16, +} + +impl Config { + pub fn new(host: String, port: u16) -> Self { + Config { host, port } + } + + pub fn load(&self) -> Result<(), std::io::Error> { + Ok(()) + } +} + +pub struct Processor { + config: Config, + cache: HashMap, +} + +impl Processor { + pub fn new(config: Config) -> Self { + Processor { + config, + cache: HashMap::new(), + } + } + + pub fn process(&mut self, input: &str) -> Result { + if let Some(cached) = self.cache.get(input) { + return Ok(cached.clone()); + } + + let result = format!("Processed: {}", input); + self.cache.insert(input.to_string(), result.clone()); + Ok(result) + } +} + +fn main() { + let config = Config::new("localhost".to_string(), 8080); + let mut processor = Processor::new(config); + + match processor.process("test") { + Ok(result) => println!("{}", result), + Err(e) => eprintln!("Error: {}", e), + } +} +''' + + +@pytest.fixture +def python_project(temp_project_dir: Path) -> Path: + """Create a mock Python project structure.""" + src_dir = temp_project_dir / "src" + src_dir.mkdir(exist_ok=True) + + (src_dir / "__init__.py").write_text('"""Package init."""') + (src_dir / "main.py").write_text(''' +"""Main module.""" + +def main(): + print("Hello, World!") + +if __name__ == "__main__": + main() +''') + + (src_dir / "utils.py").write_text(''' +"""Utility functions.""" + +def helper_function(): + """A helper function.""" + return "helper" + +class HelperClass: + """Helper class.""" + pass +''') + + (temp_project_dir / "requirements.txt").write_text(''' +requests>=2.28.0 +pyyaml>=6.0 +pytest>=7.0.0 +''') + + (temp_project_dir / "setup.py").write_text(''' +"""Setup script.""" + +from setuptools import setup, find_packages + +setup( + name="test_package", + version="0.1.0", + packages=find_packages(), + install_requires=[ + "requests>=2.28.0", + ], +) +''') + + return temp_project_dir + + +@pytest.fixture +def nodejs_project(temp_project_dir: Path) -> Path: + """Create a mock Node.js project structure.""" + (temp_project_dir / "package.json").write_text(''' +{ + "name": "test-nodejs-project", + "version": "1.0.0", + "description": "Test Node.js project", + "main": "index.js", + "scripts": { + "start": "node index.js", + "test": "jest" + }, + "dependencies": { + "express": "^4.18.0", + "lodash": "^4.17.21" + }, + "devDependencies": { + "jest": "^29.0.0" + } +} +''') + + (temp_project_dir / "index.js").write_text(''' +const express = require('express'); +const app = express(); + +app.get('/', (req, res) => { + res.send('Hello World!'); +}); + +app.listen(3000, () => { + console.log('Server running on port 3000'); +}); + +module.exports = app; +''') + + return temp_project_dir + + +@pytest.fixture +def django_project(temp_project_dir: Path) -> Path: + """Create a mock Django project structure.""" + project_dir = temp_project_dir / "project" + project_dir.mkdir(exist_ok=True) + + (temp_project_dir / "manage.py").write_text(''' +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed?" + ) from exc + execute_from_command_line(sys.argv) + +if __name__ == '__main__': + main() +''') + + (project_dir / "__init__.py").write_text('') + (project_dir / "settings.py").write_text(''' +"""Django settings for test_project.""" + +SECRET_KEY = 'test-secret-key' +DEBUG = True +ALLOWED_HOSTS = [] + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', +] + +ROOT_URLCONF = 'project.urls' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': 'db.sqlite3', + } +} +''') + + (project_dir / "urls.py").write_text(''' +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +''') + + return temp_project_dir + + +@pytest.fixture +def react_project(temp_project_dir: Path) -> Path: + """Create a mock React project structure.""" + (temp_project_dir / "package.json").write_text(''' +{ + "name": "test-react-project", + "version": "1.0.0", + "private": true, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-scripts": "5.0.1" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} +''') + + public_dir = temp_project_dir / "public" + public_dir.mkdir(exist_ok=True) + + (public_dir / "index.html").write_text(''' + + + + + React App + + + +
+ + +''') + + src_dir = temp_project_dir / "src" + src_dir.mkdir(exist_ok=True) + + (src_dir / "index.js").write_text(''' +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import App from './App'; + +const root = ReactDOM.createRoot(document.getElementById('root')); +root.render( + + + +); +''') + + (src_dir / "App.js").write_text(''' +import React from 'react'; + +function App() { + return ( +
+

Welcome to React

+
+ ); +} + +export default App; +''') + + return temp_project_dir + + +@pytest.fixture +def mixed_project(temp_project_dir: Path) -> Path: + """Create a mixed project with Python and Node.js.""" + src_dir = temp_project_dir / "src" + src_dir.mkdir(exist_ok=True) + + (temp_project_dir / "requirements.txt").write_text(''' +requests>=2.28.0 +flask>=2.0.0 +''') + + (temp_project_dir / "package.json").write_text(''' +{ + "name": "mixed-project", + "version": "1.0.0", + "dependencies": { + "express": "^4.18.0" + } +} +''') + + (src_dir / "main.py").write_text(''' +"""Main Python module.""" +from flask import Flask + +app = Flask(__name__) + +@app.route('/') +def index(): + return "Hello" +''') + + return temp_project_dir + + +@pytest.fixture +def default_config(): + """Return default configuration.""" + from codechunk.config import Config + return Config() + + +@pytest.fixture +def chunking_config(): + """Return chunking configuration.""" + from codechunk.config import ChunkingConfig + return ChunkingConfig()