Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
package billing
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDefaultPlanFeaturesFreeDeniesAI(t *testing.T) {
|
||||
m := DefaultPlanFeatures("Free", false)
|
||||
for _, key := range []string{
|
||||
"capability.ai_processing",
|
||||
"catalog.products.process_ai_titles",
|
||||
"marketing.campaigns.generate_ai",
|
||||
"settings.api_keys",
|
||||
"capability.api_access",
|
||||
"capability.email_live_send",
|
||||
} {
|
||||
if m[key] {
|
||||
t.Fatalf("Free should deny %s", key)
|
||||
}
|
||||
}
|
||||
if !m["catalog.products"] || !m["capability.normalize_specs_fill"] {
|
||||
t.Fatal("Free should allow catalog + normalize")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultPlanFeaturesCustomEnableAll(t *testing.T) {
|
||||
m := DefaultPlanFeatures("Acme Deal", true)
|
||||
for _, k := range FeatureCatalogKeys {
|
||||
if !m[k] {
|
||||
t.Fatalf("custom should enable all; missing %s", k)
|
||||
}
|
||||
}
|
||||
m2 := DefaultPlanFeatures("Enterprise", true)
|
||||
for _, k := range FeatureCatalogKeys {
|
||||
if !m2[k] {
|
||||
t.Fatalf("Enterprise (is_custom) should enable all; missing %s", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveEffectiveFeaturesGlobalSectionDisableAll(t *testing.T) {
|
||||
gates := emptyGatesView()
|
||||
gates.Sections["marketing"] = false
|
||||
features, sections, disabled := ResolveEffectiveFeatures("Growth", false, nil, gates)
|
||||
if sections["marketing"] {
|
||||
t.Fatal("marketing section should be off")
|
||||
}
|
||||
if features["marketing.campaigns"] || features["marketing.campaigns.generate_ai"] {
|
||||
t.Fatal("marketing keys must be false when section disabled")
|
||||
}
|
||||
found := false
|
||||
for _, d := range disabled {
|
||||
if d == "marketing.campaigns.generate_ai" {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("disabled_features should list marketing.campaigns.generate_ai")
|
||||
}
|
||||
if !features["catalog.products"] {
|
||||
t.Fatal("catalog should remain on")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveEffectiveFeaturesCustomOverrideFalse(t *testing.T) {
|
||||
gates := emptyGatesView()
|
||||
overrides := map[string]bool{"settings.api_keys": false}
|
||||
features, _, _ := ResolveEffectiveFeatures("Client Deal", true, overrides, gates)
|
||||
if features["settings.api_keys"] {
|
||||
t.Fatal("override false must win on custom")
|
||||
}
|
||||
if !features["capability.ai_processing"] {
|
||||
t.Fatal("other keys stay on for custom")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlanAllowsFeatureCapabilityResolution(t *testing.T) {
|
||||
if PlanAllowsFeature("Free", false, nil, "capability.ai_processing") {
|
||||
t.Fatal("Free deny AI capability")
|
||||
}
|
||||
if !PlanAllowsFeature("Starter", false, nil, "capability.ai_processing") {
|
||||
t.Fatal("Starter allow AI capability")
|
||||
}
|
||||
if PlanAllowsFeature("Starter", false, nil, "capability.byok") {
|
||||
t.Fatal("Starter deny BYOK")
|
||||
}
|
||||
if !PlanAllowsFeature("Growth", false, nil, "capability.byok") {
|
||||
t.Fatal("Growth allow BYOK")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFeatureKeyFromError(t *testing.T) {
|
||||
err := fmt.Errorf("%w: %s", ErrFeatureDisabled, "marketing.campaigns.generate_ai")
|
||||
if got := FeatureKeyFromError(err); got != "marketing.campaigns.generate_ai" {
|
||||
t.Fatalf("got %q", got)
|
||||
}
|
||||
if FeatureKeyFromError(errors.New("other")) != "" {
|
||||
t.Fatal("non-feature error should yield empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFeatureKeysForProcessingType(t *testing.T) {
|
||||
keys := FeatureKeysForProcessingType("title")
|
||||
if len(keys) != 2 || keys[0] != "capability.ai_processing" {
|
||||
t.Fatalf("title keys: %v", keys)
|
||||
}
|
||||
keys = FeatureKeysForProcessingType("normalize")
|
||||
if len(keys) != 1 || keys[0] != "capability.normalize_specs_fill" {
|
||||
t.Fatalf("normalize keys: %v", keys)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloneGatesViewIndependent(t *testing.T) {
|
||||
src := emptyGatesView()
|
||||
src.Sections["marketing"] = false
|
||||
src.Features["capability.ai_processing"] = false
|
||||
dst := cloneGatesView(src)
|
||||
dst.Sections["marketing"] = true
|
||||
dst.Features["capability.ai_processing"] = true
|
||||
if src.Sections["marketing"] {
|
||||
t.Fatal("clone must not share sections map")
|
||||
}
|
||||
if src.Features["capability.ai_processing"] {
|
||||
t.Fatal("clone must not share features map")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user