Files
pulse/pkg/licensing/upgrade_test.go
T
courtmanr@gmail.com fc5aaef391 Register the external_probe Pro entitlement
Add external_probe to the licensing feature enumeration, Pro tier
membership, self-hosted feature catalog, feature map, upgrade matrix
and pricing handoff, with the entitlement contract goldens updated.
The capability is served by the community binary - the entitlement
alone gates it, like relay. No existing free functionality changes:
local availability checks stay ungated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 11:13:04 +01:00

165 lines
5.3 KiB
Go

package licensing
import (
"strings"
"testing"
)
func TestResolveProTrialSignupURL_DefaultWhenUnset(t *testing.T) {
if got := ResolveProTrialSignupURL(""); got != DefaultProTrialSignupURL {
t.Fatalf("ResolveProTrialSignupURL(\"\") = %q, want %q", got, DefaultProTrialSignupURL)
}
}
func TestResolveProTrialSignupURL_DefaultIsHostedCommercialBase(t *testing.T) {
if strings.Contains(DefaultProTrialSignupURL, "start-pro-trial") {
t.Fatalf("DefaultProTrialSignupURL=%q must not point at retired trial signup route", DefaultProTrialSignupURL)
}
}
func TestResolveProTrialSignupURL_UsesValidOverride(t *testing.T) {
const override = "https://example.com/commercial-base?src=test"
if got := ResolveProTrialSignupURL(override); got != override {
t.Fatalf("ResolveProTrialSignupURL() = %q, want %q", got, override)
}
}
func TestResolveProTrialSignupURL_AllowsLoopbackHTTPOverride(t *testing.T) {
const override = "http://127.0.0.1:8080/commercial-base?src=test"
if got := ResolveProTrialSignupURL(override); got != override {
t.Fatalf("ResolveProTrialSignupURL() = %q, want %q", got, override)
}
}
func TestResolveProTrialSignupURL_RejectsInvalidOverrides(t *testing.T) {
testCases := []string{
"relative/path",
"javascript:alert(1)",
"https://",
"http://192.168.1.20/commercial-base",
"ftp://example.com/commercial-base",
}
for _, tc := range testCases {
t.Run(tc, func(t *testing.T) {
if got := ResolveProTrialSignupURL(tc); got != DefaultProTrialSignupURL {
t.Fatalf("ResolveProTrialSignupURL() = %q, want default %q", got, DefaultProTrialSignupURL)
}
})
}
}
func TestResolvePulseAccountPortalURL_DefaultWhenUnset(t *testing.T) {
if got := ResolvePulseAccountPortalURL(""); got != DefaultPulseAccountPortalURL {
t.Fatalf("ResolvePulseAccountPortalURL(\"\") = %q, want %q", got, DefaultPulseAccountPortalURL)
}
}
func TestResolvePulseAccountPortalURL_UsesValidOverride(t *testing.T) {
const override = "https://example.com/portal?src=test"
if got := ResolvePulseAccountPortalURL(override); got != override {
t.Fatalf("ResolvePulseAccountPortalURL() = %q, want %q", got, override)
}
}
func TestResolvePulseAccountPortalURL_AllowsLoopbackHTTPOverride(t *testing.T) {
const override = "http://localhost:8080/portal?src=test"
if got := ResolvePulseAccountPortalURL(override); got != override {
t.Fatalf("ResolvePulseAccountPortalURL() = %q, want %q", got, override)
}
}
func TestResolvePulseAccountPortalURL_RejectsInvalidOverrides(t *testing.T) {
testCases := []string{
"relative/path",
"javascript:alert(1)",
"https://",
"http://10.0.0.25/portal",
"ftp://example.com/portal",
}
for _, tc := range testCases {
t.Run(tc, func(t *testing.T) {
if got := ResolvePulseAccountPortalURL(tc); got != DefaultPulseAccountPortalURL {
t.Fatalf("ResolvePulseAccountPortalURL() = %q, want default %q", got, DefaultPulseAccountPortalURL)
}
})
}
}
func TestOperatorOutcomeUpgradeReasonsRemainCanonical(t *testing.T) {
expected := map[string]string{
FeatureRelay: "Get Relay so Pulse stays reachable securely from anywhere instead of only on the local dashboard.",
FeatureLongTermMetrics: "Get Relay for 14 days of history, or Pro for 90 days, so you can see what changed before and after an incident.",
FeatureAIAlerts: "Upgrade to Pro so Patrol can investigate issues instead of handing you a stack of symptoms.",
FeatureAIAutoFix: "Upgrade to Pro so Patrol can investigate issues, apply safe fixes within Patrol mode, and verify the result.",
}
for _, entry := range UpgradeReasonMatrix {
want, ok := expected[entry.Feature]
if !ok {
continue
}
if entry.Reason != want {
t.Fatalf("reason for %q = %q, want %q", entry.Feature, entry.Reason, want)
}
}
}
func TestCompatibilityOnlyFeaturesStayOutOfGenericUpgradeReasons(t *testing.T) {
reasons := GenerateUpgradeReasons(nil)
for _, entry := range reasons {
if entry.Feature == FeatureKubernetesAI {
t.Fatalf("compatibility-only feature %q should not produce a generic upgrade reason", entry.Feature)
}
}
}
func TestCompatibilityOnlyFeatureUpgradeURLsFallBackToGenericPricing(t *testing.T) {
foundCompatibilityOnlyFeature := false
for _, entry := range AllFeatureMetadata() {
if !IsCompatibilityOnlyFeature(entry.Key) {
continue
}
foundCompatibilityOnlyFeature = true
if got := UpgradeURLForFeature(entry.Key); got != DefaultUpgradeURL {
t.Fatalf("UpgradeURLForFeature(%q) = %q, want generic pricing URL %q", entry.Key, got, DefaultUpgradeURL)
}
}
if !foundCompatibilityOnlyFeature {
t.Fatal("expected at least one compatibility-only feature in metadata")
}
}
func TestUpgradeReasonMatrixDerivesFromCanonicalFeatureMetadata(t *testing.T) {
expectedOrder := []string{
FeatureMobileApp,
FeaturePushNotifications,
FeatureRelay,
FeatureLongTermMetrics,
FeatureAIAutoFix,
FeatureAIAlerts,
FeatureRBAC,
FeatureAgentProfiles,
FeatureExternalProbe,
FeatureAuditLogging,
FeatureAdvancedReporting,
}
if len(UpgradeReasonMatrix) != len(expectedOrder) {
t.Fatalf("UpgradeReasonMatrix length = %d, want %d", len(UpgradeReasonMatrix), len(expectedOrder))
}
for idx, feature := range expectedOrder {
if UpgradeReasonMatrix[idx].Feature != feature {
t.Fatalf("UpgradeReasonMatrix[%d].Feature = %q, want %q", idx, UpgradeReasonMatrix[idx].Feature, feature)
}
}
}