73 lines
2.4 KiB
Go
73 lines
2.4 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/descrybe/descrybe-v2/apps/api/internal/billing"
|
|
)
|
|
|
|
func TestFeatureKeyForAPIPath(t *testing.T) {
|
|
cases := []struct {
|
|
path string
|
|
want string
|
|
}{
|
|
{"/api/products", "catalog.products"},
|
|
{"/api/products/", "catalog.products"},
|
|
{"/api/products/8f14e45f-ceea-467a-9e0f-000000000000", "catalog.products"},
|
|
{"/api/api-keys", "settings.api_keys"},
|
|
{"/api/api-keys/42", "settings.api_keys"},
|
|
{"/api/marketing/calendar", "marketing.content_calendar"},
|
|
{"/api/marketing/calendar/prepare", "marketing.content_calendar"},
|
|
{"/api/integrations/ai/prompts", "integrations.ai"},
|
|
{"/api/integrations/email/test", "integrations.email"},
|
|
{"/api/woocommerce/orders", "stores.woocommerce"},
|
|
{"/api/billing/checkout", "billing.checkout"},
|
|
// Unmapped paths stay open — the middleware must not guess.
|
|
{"/api/auth/me", ""},
|
|
{"/api/billing/credits", ""},
|
|
{"/api/billing/capabilities", ""},
|
|
{"/api/unknown-thing", ""},
|
|
{"/api", ""},
|
|
}
|
|
for _, tc := range cases {
|
|
if got := featureKeyForAPIPath(tc.path); got != tc.want {
|
|
t.Errorf("featureKeyForAPIPath(%q) = %q, want %q", tc.path, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// A prefix must never match a longer sibling path segment: /api/feeds governs
|
|
// feeds.list, but /api/feeds-something-else is not a feeds route.
|
|
func TestFeatureKeyForAPIPathDoesNotMatchPartialSegments(t *testing.T) {
|
|
if got := featureKeyForAPIPath("/api/feedsomething"); got != "" {
|
|
t.Errorf("got %q, want empty", got)
|
|
}
|
|
if got := featureKeyForAPIPath("/api/products-export"); got != "" {
|
|
t.Errorf("got %q, want empty", got)
|
|
}
|
|
}
|
|
|
|
// Every key the middleware enforces must be one the owner can actually toggle,
|
|
// otherwise a route could be blocked with no way to unblock it.
|
|
func TestAPIFeatureRoutesAreGrantable(t *testing.T) {
|
|
for path, key := range apiFeatureRoutes {
|
|
if !billing.IsKnownFeatureKey(key) {
|
|
t.Errorf("%s maps to unknown feature key %q", path, key)
|
|
continue
|
|
}
|
|
if !billing.IsGrantableFeatureKey(key) {
|
|
t.Errorf("%s maps to %q, which the owner cannot toggle", path, key)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The capability matrix itself must stay reachable — it is what tells the
|
|
// dashboard which surfaces to hide.
|
|
func TestAlwaysReachablePathsAreNotGated(t *testing.T) {
|
|
for _, path := range alwaysReachableAPIPaths {
|
|
if got := featureKeyForAPIPath(path); got != "" {
|
|
t.Errorf("%s resolved to feature %q but must stay open", path, got)
|
|
}
|
|
}
|
|
}
|