package billing import ( "testing" ) func TestDefaultPlanFeaturesMatrix(t *testing.T) { t.Parallel() free := DefaultPlanFeatures("Free", false) if len(free) != len(FeatureCatalogKeys) { t.Fatalf("free matrix size=%d want %d", len(free), len(FeatureCatalogKeys)) } for _, k := range []string{ "catalog.products", "catalog.products.process_categories", "capability.normalize_specs_fill", "capability.eprel", "feeds.list", "billing.overview", } { if !free[k] { t.Fatalf("free should allow %s", k) } } for _, k := range []string{ "catalog.products.process_ai_titles", "marketing.campaigns.generate_ai", "marketing.campaigns.send", "settings.api_keys", "capability.ai_processing", "capability.byok", "integrations.ai.byok", } { if free[k] { t.Fatalf("free should deny %s", k) } } starter := DefaultPlanFeatures("Starter", false) if !starter["catalog.products.process_ai_titles"] { t.Fatal("starter should allow AI titles") } if starter["integrations.ai.byok"] || starter["capability.byok"] { t.Fatal("starter should deny BYOK") } growth := DefaultPlanFeatures("Growth", false) for _, k := range FeatureCatalogKeys { if !growth[k] { t.Fatalf("growth should allow all keys; %s is off", k) } } business := DefaultPlanFeatures("Business", false) for _, k := range FeatureCatalogKeys { if !business[k] { t.Fatalf("business should allow all keys; %s is off", k) } } enterprise := DefaultPlanFeatures("Enterprise", true) for _, k := range FeatureCatalogKeys { if !enterprise[k] { t.Fatalf("enterprise custom should allow all keys; %s is off", k) } } custom := DefaultPlanFeatures("ClientCo Deal", true) for _, k := range FeatureCatalogKeys { if !custom[k] { t.Fatalf("custom should allow all keys; %s is off", k) } } } func TestSparseDefaultOverrides(t *testing.T) { t.Parallel() free := SparseDefaultOverrides("Free", false) if len(free) == 0 { t.Fatal("free sparse overrides should list denied keys") } for k, v := range free { if v { t.Fatalf("sparse override for %s should be false", k) } } if SparseDefaultOverrides("Growth", false) == nil { t.Fatal("expected empty map not nil") } if len(SparseDefaultOverrides("Growth", false)) != 0 { t.Fatal("growth sparse should be empty") } if len(SparseDefaultOverrides("Anything", true)) != 0 { t.Fatal("custom sparse should be empty") } if len(SparseDefaultOverrides("A1", false)) == 0 { t.Fatal("legacy A1 sparse should list denied keys") } a1PaygSparse := SparseDefaultOverrides("A1", true) if len(a1PaygSparse) == 0 { t.Fatal("A1 PAYG custom sparse should list Stores/AI denied keys") } if a1PaygSparse["stores.hub"] != false || a1PaygSparse["integrations.ai"] != false { t.Fatalf("A1 PAYG sparse must deny stores/AI: %#v", a1PaygSparse) } if _, ok := a1PaygSparse["processing.monitor"]; ok { t.Fatal("A1 PAYG sparse must not list allowed keys") } } func TestNormalizePublicPlanName(t *testing.T) { t.Parallel() cases := map[string]string{ "": "free", "Free": "free", "STARTER": "starter", "Growth": "growth", "Business": "business", "Enterprise": "enterprise", "A1": "other", } for in, want := range cases { if got := NormalizePublicPlanName(in); got != want { t.Fatalf("NormalizePublicPlanName(%q)=%q want %q", in, got, want) } } } func TestPlanAllowsFeatureUsesOverrides(t *testing.T) { t.Parallel() if PlanAllowsFeature("Free", false, map[string]bool{"settings.api_keys": true}, "settings.api_keys") != true { t.Fatal("override true should win on free") } if PlanAllowsFeature("Free", false, nil, "settings.api_keys") != false { t.Fatal("free default denies api keys") } if PlanAllowsFeature("Deal", true, nil, "settings.api_keys") != true { t.Fatal("custom allows all") } }