116 lines
3.0 KiB
Go
116 lines
3.0 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
func buildMountedRouter() http.Handler {
|
|
r := chi.NewRouter()
|
|
Mount(r)
|
|
return r
|
|
}
|
|
|
|
func TestRoutes_7_1_1_AnalyzeEndpointExists(t *testing.T) {
|
|
resetRateLimiter()
|
|
r := buildMountedRouter()
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/analyze", nil)
|
|
rr := httptest.NewRecorder()
|
|
r.ServeHTTP(rr, req)
|
|
|
|
if rr.Code == http.StatusNotFound {
|
|
t.Fatalf("expected /api/analyze endpoint to exist")
|
|
}
|
|
}
|
|
|
|
func TestRoutes_7_1_2_POSTMethodWorks(t *testing.T) {
|
|
resetRateLimiter()
|
|
r := buildMountedRouter()
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/analyze", nil)
|
|
rr := httptest.NewRecorder()
|
|
r.ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusBadRequest && rr.Code != http.StatusOK && rr.Code != http.StatusInternalServerError {
|
|
t.Fatalf("expected handled POST status, got %d", rr.Code)
|
|
}
|
|
}
|
|
|
|
func TestRoutes_7_1_3_GETMethodReturnsMethodNotAllowed(t *testing.T) {
|
|
resetRateLimiter()
|
|
r := buildMountedRouter()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/analyze", nil)
|
|
rr := httptest.NewRecorder()
|
|
r.ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusMethodNotAllowed {
|
|
t.Fatalf("expected 405 for GET /api/analyze, got %d", rr.Code)
|
|
}
|
|
}
|
|
|
|
func TestRoutes_7_1_4_UnknownRoutesReturn404(t *testing.T) {
|
|
resetRateLimiter()
|
|
r := buildMountedRouter()
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/unknown", nil)
|
|
rr := httptest.NewRecorder()
|
|
r.ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusNotFound {
|
|
t.Fatalf("expected 404 for unknown route, got %d", rr.Code)
|
|
}
|
|
}
|
|
|
|
func TestRoutes_7_2_1_CORSAppliedBeforeRateLimit(t *testing.T) {
|
|
resetRateLimiter()
|
|
withFixedNow(t, timeNow())
|
|
r := buildMountedRouter()
|
|
|
|
for i := 0; i < 10; i++ {
|
|
req := httptest.NewRequest(http.MethodPost, "/api/analyze", nil)
|
|
req.Header.Set("Origin", "http://localhost:5173")
|
|
req.RemoteAddr = "127.0.0.1:12345"
|
|
rr := httptest.NewRecorder()
|
|
r.ServeHTTP(rr, req)
|
|
}
|
|
|
|
blockedReq := httptest.NewRequest(http.MethodPost, "/api/analyze", nil)
|
|
blockedReq.Header.Set("Origin", "http://localhost:5173")
|
|
blockedReq.RemoteAddr = "127.0.0.1:12345"
|
|
blockedResp := httptest.NewRecorder()
|
|
r.ServeHTTP(blockedResp, blockedReq)
|
|
|
|
if blockedResp.Code != http.StatusTooManyRequests {
|
|
t.Fatalf("expected 429 after limit, got %d", blockedResp.Code)
|
|
}
|
|
if got := blockedResp.Header().Get("Access-Control-Allow-Origin"); got != "http://localhost:5173" {
|
|
t.Fatalf("expected CORS header on rate-limited response, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestRoutes_7_2_2_RateLimitingAppliedToAPIRoutes(t *testing.T) {
|
|
resetRateLimiter()
|
|
r := buildMountedRouter()
|
|
|
|
for i := 0; i < 10; i++ {
|
|
req := httptest.NewRequest(http.MethodPost, "/api/analyze", nil)
|
|
req.RemoteAddr = "127.0.0.1:12345"
|
|
rr := httptest.NewRecorder()
|
|
r.ServeHTTP(rr, req)
|
|
}
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/analyze", nil)
|
|
req.RemoteAddr = "127.0.0.1:12345"
|
|
rr := httptest.NewRecorder()
|
|
r.ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusTooManyRequests {
|
|
t.Fatalf("expected 429 on 11th /api/analyze request, got %d", rr.Code)
|
|
}
|
|
}
|