package billing import ( "context" "errors" "fmt" "strings" "testing" ) func TestDefaultPlanFeaturesStarterBYOK(t *testing.T) { m := DefaultPlanFeatures("Starter", false) if !m["catalog.products.process_ai_titles"] { t.Fatal("Starter should allow AI titles") } if m["integrations.ai.byok"] || m["capability.byok"] { t.Fatal("Starter should deny BYOK") } } func TestDefaultPlanFeaturesGrowthAllOn(t *testing.T) { m := DefaultPlanFeatures("Growth", false) for _, k := range FeatureCatalogKeys { if !m[k] { t.Fatalf("Growth should allow %s", k) } } } func TestPlanAllowsOverrideFalseWins(t *testing.T) { overrides := map[string]bool{"settings.api_keys": false} if PlanAllowsFeature("Growth", false, overrides, "settings.api_keys") { t.Fatal("override false should win on Growth") } } func TestResolveFeaturesGlobalFeatureOff(t *testing.T) { gates := FeatureGatesView{ Sections: map[string]bool{}, Features: map[string]bool{"capability.byok": false}, } features := ResolveFeatures("Business", false, nil, gates) if features["capability.byok"] { t.Fatal("global feature kill-switch should win") } } func TestSparseDefaultOverridesFree(t *testing.T) { sparse := SparseDefaultOverrides("Free", false) if sparse["catalog.products.process_ai_titles"] != false { t.Fatal("expected sparse false for AI titles") } if _, ok := sparse["catalog.products"]; ok { t.Fatal("ON keys should not appear in sparse overrides") } if len(SparseDefaultOverrides("Acme", true)) != 0 { t.Fatal("custom sparse should be empty") } } func TestValidateFeatureOverridesRejectsUnknown(t *testing.T) { err := validateFeatureOverrides(map[string]bool{"not.a.real.key": true}) if !errors.Is(err, ErrUnknownFeatureKey) { t.Fatalf("want ErrUnknownFeatureKey, got %v", err) } } func TestListFeaturesCatalogComplete(t *testing.T) { s := &Service{} list, err := s.ListFeatures(context.Background()) if err != nil { t.Fatal(err) } if len(list) != len(FeatureCatalogKeys) { t.Fatalf("got %d want %d", len(list), len(FeatureCatalogKeys)) } if list[0].Section == "" { t.Fatal("section required") } } func TestAssertFeatureErrorWraps(t *testing.T) { err := fmt.Errorf("%w: %s", ErrFeatureDisabled, "marketing.campaigns.generate_ai") if !errors.Is(err, ErrFeatureDisabled) { t.Fatal(err) } if !strings.Contains(err.Error(), "marketing.campaigns.generate_ai") { t.Fatal(err) } }