266
tests/unit/test_detectors.py
Normal file
266
tests/unit/test_detectors.py
Normal file
@@ -0,0 +1,266 @@
|
||||
"""Tests for endpoint detectors."""
|
||||
|
||||
import pytest
|
||||
import tempfile
|
||||
import os
|
||||
from pathlib import Path
|
||||
from docgen.models import HTTPMethod
|
||||
|
||||
|
||||
class TestPythonDetector:
|
||||
"""Tests for PythonDetector."""
|
||||
|
||||
def test_fastapi_detection(self):
|
||||
"""Test FastAPI endpoint detection."""
|
||||
code = '''
|
||||
from fastapi import FastAPI, APIRouter
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/users")
|
||||
async def get_users():
|
||||
return {"users": []}
|
||||
|
||||
@app.post("/users")
|
||||
async def create_user():
|
||||
return {"id": 1}
|
||||
|
||||
router = APIRouter()
|
||||
@router.get("/items")
|
||||
async def get_items():
|
||||
return {"items": []}
|
||||
'''
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
|
||||
f.write(code)
|
||||
f.flush()
|
||||
|
||||
from docgen.detectors import PythonDetector
|
||||
detector = PythonDetector()
|
||||
endpoints = detector.detect_endpoints(Path(f.name))
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
assert len(endpoints) >= 3
|
||||
methods = [e.method for e in endpoints]
|
||||
assert HTTPMethod.GET in methods
|
||||
assert HTTPMethod.POST in methods
|
||||
|
||||
def test_flask_detection(self):
|
||||
"""Test Flask endpoint detection."""
|
||||
code = '''
|
||||
from flask import Flask, Blueprint
|
||||
|
||||
app = Flask(__name__)
|
||||
blueprint = Blueprint("api", __name__)
|
||||
|
||||
@blueprint.route("/items")
|
||||
def get_items():
|
||||
return {"items": []}
|
||||
|
||||
@blueprint.route("/items", methods=["POST"])
|
||||
def create_item():
|
||||
return {"id": 1}
|
||||
'''
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
|
||||
f.write(code)
|
||||
f.flush()
|
||||
|
||||
from docgen.detectors import PythonDetector
|
||||
detector = PythonDetector()
|
||||
endpoints = detector.detect_endpoints(Path(f.name))
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
assert len(endpoints) >= 2
|
||||
|
||||
def test_django_detection(self):
|
||||
"""Test Django URL pattern detection."""
|
||||
code = '''
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path("users/", views.UserListView.as_view()),
|
||||
path("users/<int:pk>/", views.UserDetailView.as_view()),
|
||||
]
|
||||
'''
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
|
||||
f.write(code)
|
||||
f.flush()
|
||||
|
||||
from docgen.detectors import PythonDetector
|
||||
detector = PythonDetector()
|
||||
endpoints = detector.detect_endpoints(Path(f.name))
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
assert len(endpoints) == 2
|
||||
assert endpoints[0].path == "users/"
|
||||
assert endpoints[1].path == "users/<int:pk>/"
|
||||
|
||||
|
||||
class TestJavaScriptDetector:
|
||||
"""Tests for JavaScriptDetector."""
|
||||
|
||||
def test_express_detection(self):
|
||||
"""Test Express endpoint detection."""
|
||||
code = '''
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/users", (req, res) => {
|
||||
res.json({ users: [] });
|
||||
});
|
||||
|
||||
router.post("/users", (req, res) => {
|
||||
res.json({ id: 1 });
|
||||
});
|
||||
'''
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.js', delete=False) as f:
|
||||
f.write(code)
|
||||
f.flush()
|
||||
|
||||
from docgen.detectors import JavaScriptDetector
|
||||
detector = JavaScriptDetector()
|
||||
endpoints = detector.detect_endpoints(Path(f.name))
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
assert len(endpoints) >= 2
|
||||
|
||||
def test_fastify_detection(self):
|
||||
"""Test Fastify endpoint detection."""
|
||||
code = '''
|
||||
const fastify = require("fastify")();
|
||||
|
||||
fastify.get("/items", async (request, reply) => {
|
||||
return { items: [] };
|
||||
});
|
||||
|
||||
fastify.post("/items", async (request, reply) => {
|
||||
return { id: 1 };
|
||||
});
|
||||
'''
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.js', delete=False) as f:
|
||||
f.write(code)
|
||||
f.flush()
|
||||
|
||||
from docgen.detectors import JavaScriptDetector
|
||||
detector = JavaScriptDetector()
|
||||
endpoints = detector.detect_endpoints(Path(f.name))
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
assert len(endpoints) >= 2
|
||||
|
||||
|
||||
class TestGoDetector:
|
||||
"""Tests for GoDetector."""
|
||||
|
||||
def test_gin_detection(self):
|
||||
"""Test Gin endpoint detection."""
|
||||
code = '''
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := gin.Default()
|
||||
r.GET("/users", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{"users": []})
|
||||
})
|
||||
r.POST("/users", func(c *gin.Context) {
|
||||
c.JSON(201, gin.H{"id": 1})
|
||||
})
|
||||
}
|
||||
'''
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.go', delete=False) as f:
|
||||
f.write(code)
|
||||
f.flush()
|
||||
|
||||
from docgen.detectors import GoDetector
|
||||
detector = GoDetector()
|
||||
endpoints = detector.detect_endpoints(Path(f.name))
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
assert len(endpoints) >= 2
|
||||
|
||||
def test_chi_detection(self):
|
||||
"""Test chi endpoint detection."""
|
||||
code = '''
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := chi.NewRouter()
|
||||
r.GET("/items", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(`{"items": []}`))
|
||||
})
|
||||
r.POST("/items", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(`{"id": 1}`))
|
||||
})
|
||||
}
|
||||
'''
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.go', delete=False) as f:
|
||||
f.write(code)
|
||||
f.flush()
|
||||
|
||||
from docgen.detectors import GoDetector
|
||||
detector = GoDetector()
|
||||
endpoints = detector.detect_endpoints(Path(f.name))
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
assert len(endpoints) >= 2
|
||||
|
||||
|
||||
class TestRustDetector:
|
||||
"""Tests for RustDetector."""
|
||||
|
||||
def test_actix_detection(self):
|
||||
"""Test Actix-web endpoint detection."""
|
||||
code = '''
|
||||
use actix_web::{web, App, HttpResponse};
|
||||
|
||||
#[get("/users")]
|
||||
async fn list_users() -> HttpResponse {
|
||||
HttpResponse::Ok().json(vec![])
|
||||
}
|
||||
|
||||
#[post("/users")]
|
||||
async fn create_user() -> HttpResponse {
|
||||
HttpResponse::Created().json(serde_json::json!({"id": 1}))
|
||||
}
|
||||
'''
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.rs', delete=False) as f:
|
||||
f.write(code)
|
||||
f.flush()
|
||||
|
||||
from docgen.detectors import RustDetector
|
||||
detector = RustDetector()
|
||||
endpoints = detector.detect_endpoints(Path(f.name))
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
assert len(endpoints) >= 0
|
||||
|
||||
|
||||
class TestBaseDetector:
|
||||
"""Tests for BaseDetector functionality."""
|
||||
|
||||
def test_can_detect(self):
|
||||
"""Test file extension detection."""
|
||||
from docgen.detectors import PythonDetector, JavaScriptDetector
|
||||
|
||||
py_detector = PythonDetector()
|
||||
js_detector = JavaScriptDetector()
|
||||
|
||||
assert py_detector.can_detect(Path("test.py")) is True
|
||||
assert py_detector.can_detect(Path("test.js")) is False
|
||||
assert js_detector.can_detect(Path("test.ts")) is True
|
||||
assert js_detector.can_detect(Path("test.py")) is False
|
||||
Reference in New Issue
Block a user