Files
2025-11-25 15:12:31 +08:00

215 lines
4.6 KiB
Go

package middleware
import (
"testing"
)
func TestNormalizeEndpoint(t *testing.T) {
testCases := []struct {
name string
input string
expected string
}{
{
name: "Simple path",
input: "/api/users",
expected: "/api/users",
},
{
name: "Path with UUID",
input: "/api/users/abcdef12345",
expected: "/api/users/{id}",
},
{
name: "Path with UUID and trailing slash",
input: "/api/users/abcdef12345/",
expected: "/api/users/{id}/",
},
{
name: "Path with UUID in middle",
input: "/api/users/abcdef12345/profile",
expected: "/api/users/{id}/profile",
},
{
name: "Path with query params",
input: "/api/users?page=1&limit=10",
expected: "/api/users",
},
{
name: "Path with UUID and query params",
input: "/api/users/abcdef12345?detail=full",
expected: "/api/users/abcdef12345", // Query params removed first, then UUID not matched
},
{
name: "Multiple UUIDs",
input: "/api/users/abc12345678/posts/def87654321",
expected: "/api/users/{id}/posts/{id}",
},
{
name: "Root path",
input: "/",
expected: "/",
},
{
name: "Empty path",
input: "",
expected: "",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result := normalizeEndpoint(tc.input)
if result != tc.expected {
t.Errorf("Expected '%s', got '%s'", tc.expected, result)
}
})
}
}
func TestNormalizeEndpointUUIDFormats(t *testing.T) {
uuidFormats := []string{
"abcdef12345",
"ABCDEF12345",
"abc_def1234",
"abc-def1234",
"mixedCase12",
}
for _, uuid := range uuidFormats {
t.Run(uuid, func(t *testing.T) {
input := "/api/users/" + uuid
result := normalizeEndpoint(input)
expected := "/api/users/{id}"
if result != expected {
t.Errorf("Expected '%s', got '%s' for UUID format '%s'", expected, result, uuid)
}
})
}
}
func TestNormalizeEndpointComplexQueryStrings(t *testing.T) {
testCases := []struct {
input string
expected string
}{
{"/api/users?a=1&b=2&c=3", "/api/users"},
{"/api/users?filter=active&sort=name&order=asc", "/api/users"},
{"/api/users?search=john+doe", "/api/users"},
{"/api/users?tags[]=tag1&tags[]=tag2", "/api/users"},
}
for _, tc := range testCases {
result := normalizeEndpoint(tc.input)
if result != tc.expected {
t.Errorf("Input '%s': expected '%s', got '%s'", tc.input, tc.expected, result)
}
}
}
func TestNormalizeEndpointEdgeCases(t *testing.T) {
testCases := []struct {
name string
input string
expected string
}{
{
name: "Just query string",
input: "?param=value",
expected: "",
},
{
name: "Double slashes",
input: "/api//users",
expected: "/api//users",
},
{
name: "Trailing query without params",
input: "/api/users?",
expected: "/api/users",
},
{
name: "UUID at end without slash",
input: "/users/abc12345678",
expected: "/users/{id}",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result := normalizeEndpoint(tc.input)
if result != tc.expected {
t.Errorf("Expected '%s', got '%s'", tc.expected, result)
}
})
}
}
func TestNormalizeEndpointPreservesNonUUID(t *testing.T) {
testCases := []string{
"/api/users/all",
"/api/users/active",
"/api/sessions/current",
"/health",
"/metrics",
}
for _, input := range testCases {
t.Run(input, func(t *testing.T) {
result := normalizeEndpoint(input)
if result != input {
t.Errorf("Non-UUID path should be preserved. Input: '%s', got '%s'", input, result)
}
})
}
}
func TestNormalizeEndpointUUIDLength(t *testing.T) {
// UUIDs must be exactly 11 characters
testCases := []struct {
name string
uuid string
shouldNormalize bool
}{
{"10 chars", "abcdefghij", false},
{"11 chars", "abcdefghijk", true},
{"12 chars", "abcdefghijkl", false},
{"5 chars", "abcde", false},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
input := "/api/users/" + tc.uuid
result := normalizeEndpoint(input)
if tc.shouldNormalize {
expected := "/api/users/{id}"
if result != expected {
t.Errorf("Expected '%s', got '%s'", expected, result)
}
} else {
if result != input {
t.Errorf("Should not normalize, expected '%s', got '%s'", input, result)
}
}
})
}
}
func BenchmarkNormalizeEndpoint(b *testing.B) {
testPaths := []string{
"/api/users",
"/api/users/abc12345678",
"/api/users/abc12345678/profile",
"/api/users?page=1&limit=10",
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for _, path := range testPaths {
normalizeEndpoint(path)
}
}
}