mirror of
https://github.com/lukaszraczylo/gohoarder.git
synced 2026-10-12 00:45:16 +00:00
The automated update changed only go.mod, so the build failed on the old v2 imports. This commit moves the code to the v3 API. The commit replaces BodyParser with Bind().Body, Static with the static middleware, and ListenTLS with ListenConfig. It also updates the tests for TestConfig. Fixes #179
299 lines
7.2 KiB
Go
299 lines
7.2 KiB
Go
package app
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v3"
|
|
"github.com/lukaszraczylo/gohoarder/pkg/analytics"
|
|
"github.com/stretchr/testify/suite"
|
|
)
|
|
|
|
type AnalyticsHandlersTestSuite struct {
|
|
suite.Suite
|
|
app *fiber.App
|
|
appInst *App
|
|
engine *analytics.Engine
|
|
}
|
|
|
|
func (s *AnalyticsHandlersTestSuite) SetupTest() {
|
|
// Create analytics engine
|
|
s.engine = analytics.NewEngine(analytics.Config{
|
|
MaxEvents: 10000,
|
|
FlushInterval: 5 * time.Minute,
|
|
})
|
|
|
|
// Seed some test data
|
|
s.engine.TrackDownload(analytics.PackageDownload{
|
|
Registry: "npm",
|
|
Name: "lodash",
|
|
Version: "4.17.21",
|
|
Timestamp: time.Now(),
|
|
BytesSize: 1024,
|
|
})
|
|
s.engine.TrackDownload(analytics.PackageDownload{
|
|
Registry: "npm",
|
|
Name: "react",
|
|
Version: "18.0.0",
|
|
Timestamp: time.Now(),
|
|
BytesSize: 2048,
|
|
})
|
|
s.engine.TrackDownload(analytics.PackageDownload{
|
|
Registry: "pypi",
|
|
Name: "requests",
|
|
Version: "2.28.0",
|
|
Timestamp: time.Now(),
|
|
BytesSize: 512,
|
|
})
|
|
|
|
// Create app instance
|
|
s.appInst = &App{
|
|
analyticsEngine: s.engine,
|
|
}
|
|
|
|
// Create Fiber app
|
|
s.app = fiber.New()
|
|
|
|
// Register routes
|
|
s.app.Get("/api/analytics/top", s.appInst.handleAnalyticsTopPackages)
|
|
s.app.Get("/api/analytics/trending", s.appInst.handleAnalyticsTrendingPackages)
|
|
s.app.Get("/api/analytics/trends", s.appInst.handleAnalyticsTrends)
|
|
s.app.Get("/api/analytics/total", s.appInst.handleAnalyticsTotalStats)
|
|
s.app.Get("/api/analytics/registry/:registry", s.appInst.handleAnalyticsRegistryStats)
|
|
s.app.Get("/api/analytics/package/:registry/:name", s.appInst.handleAnalyticsPackageStats)
|
|
s.app.Get("/api/analytics/search", s.appInst.handleAnalyticsSearch)
|
|
}
|
|
|
|
func (s *AnalyticsHandlersTestSuite) TearDownTest() {
|
|
if s.engine != nil {
|
|
s.engine.Close()
|
|
}
|
|
}
|
|
|
|
func TestAnalyticsHandlersTestSuite(t *testing.T) {
|
|
suite.Run(t, new(AnalyticsHandlersTestSuite))
|
|
}
|
|
|
|
func (s *AnalyticsHandlersTestSuite) TestHandleAnalyticsTopPackages() {
|
|
tests := []struct {
|
|
name string
|
|
queryParams string
|
|
expectedStatus int
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "get top packages default",
|
|
queryParams: "",
|
|
expectedStatus: 200,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "get top packages with limit",
|
|
queryParams: "?limit=5",
|
|
expectedStatus: 200,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "get top packages with registry filter",
|
|
queryParams: "?registry=npm",
|
|
expectedStatus: 200,
|
|
expectError: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
s.Run(tt.name, func() {
|
|
req := httptest.NewRequest("GET", "/api/analytics/top"+tt.queryParams, nil)
|
|
resp, err := s.app.Test(req)
|
|
s.Require().NoError(err)
|
|
s.Equal(tt.expectedStatus, resp.StatusCode)
|
|
|
|
if !tt.expectError {
|
|
var result struct {
|
|
Packages []analytics.PackageStats `json:"packages"`
|
|
Total int `json:"total"`
|
|
}
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
s.NoError(err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (s *AnalyticsHandlersTestSuite) TestHandleAnalyticsTrendingPackages() {
|
|
req := httptest.NewRequest("GET", "/api/analytics/trending", nil)
|
|
resp, err := s.app.Test(req)
|
|
s.Require().NoError(err)
|
|
s.Equal(200, resp.StatusCode)
|
|
|
|
var result struct {
|
|
Packages []analytics.PackageStats `json:"packages"`
|
|
Total int `json:"total"`
|
|
}
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
s.NoError(err)
|
|
}
|
|
|
|
func (s *AnalyticsHandlersTestSuite) TestHandleAnalyticsTrends() {
|
|
tests := []struct {
|
|
name string
|
|
queryParams string
|
|
expectedStatus int
|
|
}{
|
|
{
|
|
name: "get trends default timeframe",
|
|
queryParams: "",
|
|
expectedStatus: 200,
|
|
},
|
|
{
|
|
name: "get trends with registry filter",
|
|
queryParams: "?registry=npm",
|
|
expectedStatus: 200,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
s.Run(tt.name, func() {
|
|
req := httptest.NewRequest("GET", "/api/analytics/trends"+tt.queryParams, nil)
|
|
resp, err := s.app.Test(req)
|
|
s.Require().NoError(err)
|
|
s.Equal(tt.expectedStatus, resp.StatusCode)
|
|
})
|
|
}
|
|
}
|
|
|
|
func (s *AnalyticsHandlersTestSuite) TestHandleAnalyticsTotalStats() {
|
|
req := httptest.NewRequest("GET", "/api/analytics/total", nil)
|
|
resp, err := s.app.Test(req)
|
|
s.Require().NoError(err)
|
|
s.Equal(200, resp.StatusCode)
|
|
|
|
var result struct {
|
|
TotalDownloads int64 `json:"total_downloads"`
|
|
TotalBytes int64 `json:"total_bytes"`
|
|
UniquePackages int `json:"unique_packages"`
|
|
}
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
s.NoError(err)
|
|
s.Greater(result.TotalDownloads, int64(0))
|
|
}
|
|
|
|
func (s *AnalyticsHandlersTestSuite) TestHandleAnalyticsRegistryStats() {
|
|
tests := []struct {
|
|
name string
|
|
registry string
|
|
expectedStatus int
|
|
}{
|
|
{
|
|
name: "npm registry stats",
|
|
registry: "npm",
|
|
expectedStatus: 200,
|
|
},
|
|
{
|
|
name: "pypi registry stats",
|
|
registry: "pypi",
|
|
expectedStatus: 200,
|
|
},
|
|
{
|
|
name: "go registry stats",
|
|
registry: "go",
|
|
expectedStatus: 200,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
s.Run(tt.name, func() {
|
|
req := httptest.NewRequest("GET", "/api/analytics/registry/"+tt.registry, nil)
|
|
resp, err := s.app.Test(req)
|
|
s.Require().NoError(err)
|
|
s.Equal(tt.expectedStatus, resp.StatusCode)
|
|
})
|
|
}
|
|
}
|
|
|
|
func (s *AnalyticsHandlersTestSuite) TestHandleAnalyticsPackageStats() {
|
|
tests := []struct {
|
|
name string
|
|
registry string
|
|
packageName string
|
|
expectedStatus int
|
|
}{
|
|
{
|
|
name: "lodash package stats",
|
|
registry: "npm",
|
|
packageName: "lodash",
|
|
expectedStatus: 200,
|
|
},
|
|
{
|
|
name: "react package stats",
|
|
registry: "npm",
|
|
packageName: "react",
|
|
expectedStatus: 200,
|
|
},
|
|
{
|
|
name: "requests package stats",
|
|
registry: "pypi",
|
|
packageName: "requests",
|
|
expectedStatus: 200,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
s.Run(tt.name, func() {
|
|
req := httptest.NewRequest("GET", "/api/analytics/package/"+tt.registry+"/"+tt.packageName, nil)
|
|
resp, err := s.app.Test(req)
|
|
s.Require().NoError(err)
|
|
s.Equal(tt.expectedStatus, resp.StatusCode)
|
|
})
|
|
}
|
|
}
|
|
|
|
func (s *AnalyticsHandlersTestSuite) TestHandleAnalyticsSearch() {
|
|
tests := []struct {
|
|
name string
|
|
queryParams string
|
|
expectedStatus int
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "search for lodash",
|
|
queryParams: "?q=lodash",
|
|
expectedStatus: 200,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "search for react",
|
|
queryParams: "?q=react",
|
|
expectedStatus: 200,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "search with no query",
|
|
queryParams: "",
|
|
expectedStatus: 400, // Query parameter is required
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
s.Run(tt.name, func() {
|
|
req := httptest.NewRequest("GET", "/api/analytics/search"+tt.queryParams, nil)
|
|
resp, err := s.app.Test(req)
|
|
s.Require().NoError(err)
|
|
s.Equal(tt.expectedStatus, resp.StatusCode)
|
|
|
|
if !tt.expectError {
|
|
var result struct {
|
|
Query string `json:"query"`
|
|
Results []analytics.PackageStats `json:"results"`
|
|
Total int `json:"total"`
|
|
}
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
s.NoError(err)
|
|
}
|
|
})
|
|
}
|
|
}
|