91 lines
2.4 KiB
Go
91 lines
2.4 KiB
Go
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)
|
||
|
|
}
|
||
|
|
}
|