Files
upstream-chi/context_test.go
upstream-mirror 72c9f2ee75
Some checks failed
Test / test (1.24.x, ubuntu-latest) (push) Successful in 2m56s
Test / test (1.25.x, ubuntu-latest) (push) Successful in 2m15s
Test / test (1.26.x, ubuntu-latest) (push) Successful in 2m23s
Test / test (1.27.x, ubuntu-latest) (push) Failing after 3m56s
Test / test (1.24.x, windows-latest) (push) Has been cancelled
Test / test (1.25.x, windows-latest) (push) Has been cancelled
Test / test (1.26.x, windows-latest) (push) Has been cancelled
Test / test (1.27.x, windows-latest) (push) Has been cancelled
snapshot of https://github.com/go-chi/chi.git (master, 2026-09-15; blobs > 131072B omitted)
2026-09-15 21:48:17 +05:00

156 lines
4.4 KiB
Go

package chi
import (
"context"
"testing"
)
// TestRoutePattern tests correct in-the-middle wildcard removals.
// If user organizes a router like this:
//
// (router.go)
//
// r.Route("/v1", func(r chi.Router) {
// r.Mount("/resources", resourcesController{}.Router())
// }
//
// (resources_controller.go)
//
// r.Route("/", func(r chi.Router) {
// r.Get("/{resource_id}", getResource())
// // other routes...
// }
//
// This test checks how the route pattern is calculated
// "/v1/resources/{resource_id}" (right)
// "/v1/resources/*/{resource_id}" (wrong)
func TestRoutePattern(t *testing.T) {
routePatterns := []string{
"/v1/*",
"/resources/*",
"/{resource_id}",
}
x := &Context{
RoutePatterns: routePatterns,
}
if p := x.RoutePattern(); p != "/v1/resources/{resource_id}" {
t.Fatal("unexpected route pattern: " + p)
}
x.RoutePatterns = []string{
"/v1/*",
"/resources/*",
// Additional wildcard, depending on the router structure of the user
"/*",
"/{resource_id}",
}
// Correctly removes in-the-middle wildcards instead of "/v1/resources/*/{resource_id}"
if p := x.RoutePattern(); p != "/v1/resources/{resource_id}" {
t.Fatal("unexpected route pattern: " + p)
}
x.RoutePatterns = []string{
"/v1/*",
"/resources/*",
// Even with many wildcards
"/*",
"/*",
"/*",
"/{resource_id}/*", // Keeping trailing wildcard
}
// Correctly removes in-the-middle wildcards instead of "/v1/resources/*/*/{resource_id}/*"
if p := x.RoutePattern(); p != "/v1/resources/{resource_id}/*" {
t.Fatal("unexpected route pattern: " + p)
}
x.RoutePatterns = []string{
"/v1/*",
"/resources/*",
// And respects asterisks as part of the paths
"/*special_path/*",
"/with_asterisks*/*",
"/{resource_id}",
}
// Correctly removes in-the-middle wildcards instead of "/v1/resourcesspecial_path/with_asterisks{resource_id}"
if p := x.RoutePattern(); p != "/v1/resources/*special_path/with_asterisks*/{resource_id}" {
t.Fatal("unexpected route pattern: " + p)
}
// Testing for the root route pattern
x.RoutePatterns = []string{"/"}
// It should just return "/" as the pattern
if p := x.RoutePattern(); p != "/" {
t.Fatal("unexpected route pattern for root: " + p)
}
// Testing empty route pattern for nil context
var nilContext *Context
if p := nilContext.RoutePattern(); p != "" {
t.Fatalf("unexpected non-empty route pattern for nil context: %q", p)
}
}
// TestReplaceWildcardsConsecutive ensures multiple consecutive wildcards are
// collapsed into a single slash.
func TestReplaceWildcardsConsecutive(t *testing.T) {
if p := replaceWildcards("/foo/*/*/*/bar"); p != "/foo/bar" {
t.Fatalf("unexpected wildcard replacement: %s", p)
}
if p := replaceWildcards("/foo/*/*/*/bar/*"); p != "/foo/bar/*" {
t.Fatalf("unexpected trailing wildcard behavior: %s", p)
}
}
func TestContext_Clone(t *testing.T) {
orig := &Context{
parentCtx: context.Background(),
RoutePatterns: []string{"/v1", "/resources/{id}"},
methodsAllowed: []methodTyp{mHEAD, mGET},
URLParams: RouteParams{
Keys: []string{"foo"},
Values: []string{"bar"},
},
routeParams: RouteParams{
Keys: []string{"id"},
Values: []string{"123"},
},
}
clone := orig.Clone()
orig.Reset()
orig.URLParams.Keys = append(orig.URLParams.Keys, "bar")
orig.URLParams.Values = append(orig.URLParams.Values, "baz")
orig.routeParams.Keys = append(orig.routeParams.Keys, "name")
orig.routeParams.Values = append(orig.routeParams.Values, "foxmulder")
orig.RoutePatterns = append(orig.RoutePatterns, "/mutated")
orig.methodsAllowed = append(orig.methodsAllowed, mPOST)
if got := clone.URLParams.Keys[0]; got != "foo" {
t.Fatalf("clone URLParams.Keys was corrupted, want %q got %q", "foo", got)
}
if got := clone.URLParams.Values[0]; got != "bar" {
t.Fatalf("clone URLParams.Values was corrupted, want %q got %q", "bar", got)
}
if got := clone.routeParams.Keys[0]; got != "id" {
t.Fatalf("clone routeParams.Keys was corrupted, want %q got %q", "id", got)
}
if got := clone.routeParams.Values[0]; got != "123" {
t.Fatalf("clone routeParams.Values was corrupted, want %q got %q", "123", got)
}
if got := clone.RoutePatterns[0]; got != "/v1" {
t.Fatalf("clone RoutePatterns[0] was corrupted, want %q got %q", "/v1", got)
}
if got := clone.methodsAllowed[0]; got != mHEAD {
t.Fatalf("clone methodsAllowed[0] was corrupted, want %d got %d", mHEAD, got)
}
if clone.parentCtx != nil {
t.Fatalf("clone parentCtx should be detached, got %v", clone.parentCtx)
}
}