mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-06-03 20:13:00 +00:00
150 lines
4.4 KiB
Go
150 lines
4.4 KiB
Go
package billing
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"bookra/apps/backend/internal/config"
|
|
"bookra/apps/backend/internal/db"
|
|
"bookra/apps/backend/internal/domain"
|
|
)
|
|
|
|
func testConfig() config.Config {
|
|
return config.Config{
|
|
FrontendURL: "http://localhost:3000",
|
|
PaddleAPIKey: "pdl_sdbx_apikey_123",
|
|
PaddleWebhookKey: "pdl_ntf_123",
|
|
PaddlePriceMatrix: map[string]map[string]string{
|
|
"starter": {"czk": "pri_starter_czk", "usd": "pri_starter_usd"},
|
|
"pro": {"czk": "pri_pro_czk", "usd": "pri_pro_usd"},
|
|
"business": {"czk": "pri_business_czk", "usd": "pri_business_usd"},
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestGetSubscriptionFallsBackToSnapshotAndEntitlements(t *testing.T) {
|
|
service := NewService(testConfig(), db.NewMemoryRepository())
|
|
|
|
snapshot, err := service.GetSubscription(context.Background(), domain.Principal{
|
|
Subject: "demo-owner",
|
|
Email: "owner@bookra.dev",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("get subscription: %v", err)
|
|
}
|
|
|
|
if snapshot.PlanCode != "pro" {
|
|
t.Fatalf("expected pro, got %s", snapshot.PlanCode)
|
|
}
|
|
if snapshot.Provider != "paddle" {
|
|
t.Fatalf("expected paddle provider, got %s", snapshot.Provider)
|
|
}
|
|
if snapshot.Entitlements.MaxLocations != 3 {
|
|
t.Fatalf("expected 3 locations, got %d", snapshot.Entitlements.MaxLocations)
|
|
}
|
|
}
|
|
|
|
func TestCreateCheckoutRequiresPaddleConfig(t *testing.T) {
|
|
cfg := testConfig()
|
|
cfg.PaddleAPIKey = ""
|
|
service := NewService(cfg, db.NewMemoryRepository())
|
|
|
|
response, err := service.CreateCheckoutSession(context.Background(), domain.Principal{
|
|
Subject: "demo-owner",
|
|
Email: "owner@bookra.dev",
|
|
}, "pro", "czk")
|
|
if err != ErrPaddleNotConfigured {
|
|
t.Fatalf("expected ErrPaddleNotConfigured, got response=%v err=%v", response, err)
|
|
}
|
|
}
|
|
|
|
func TestCreateCheckoutReturnsLaunchPayload(t *testing.T) {
|
|
service := NewService(testConfig(), db.NewMemoryRepository())
|
|
|
|
response, err := service.CreateCheckoutSession(context.Background(), domain.Principal{
|
|
Subject: "demo-owner",
|
|
Email: "owner@bookra.dev",
|
|
}, "pro", "czk")
|
|
if err != nil {
|
|
t.Fatalf("create checkout: %v", err)
|
|
}
|
|
if response.PriceID != "pri_pro_czk" {
|
|
t.Fatalf("expected pri_pro_czk, got %s", response.PriceID)
|
|
}
|
|
if response.CustomData["tenantId"] == "" {
|
|
t.Fatal("expected tenantId in customData")
|
|
}
|
|
if response.SuccessRedirectURL == "" || response.CancelRedirectURL == "" {
|
|
t.Fatal("expected redirect URLs")
|
|
}
|
|
}
|
|
|
|
func TestRefreshRequiresPaddleKeyWhenCustomerExists(t *testing.T) {
|
|
cfg := testConfig()
|
|
cfg.PaddleAPIKey = ""
|
|
service := NewService(cfg, db.NewMemoryRepository())
|
|
|
|
snapshot, err := service.Refresh(context.Background(), domain.Principal{
|
|
Subject: "demo-owner",
|
|
Email: "owner@bookra.dev",
|
|
})
|
|
if err != ErrPaddleNotConfigured {
|
|
t.Fatalf("expected ErrPaddleNotConfigured, got snapshot=%v err=%v", snapshot, err)
|
|
}
|
|
}
|
|
|
|
func TestGetSubscriptionDisablesCheckoutWhenWebhookMissing(t *testing.T) {
|
|
cfg := testConfig()
|
|
cfg.PaddleWebhookKey = ""
|
|
service := NewService(cfg, db.NewMemoryRepository())
|
|
|
|
snapshot, err := service.GetSubscription(context.Background(), domain.Principal{
|
|
Subject: "demo-owner",
|
|
Email: "owner@bookra.dev",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("get subscription: %v", err)
|
|
}
|
|
if snapshot.CheckoutURLAvailable {
|
|
t.Fatal("expected checkout unavailable without webhook secret")
|
|
}
|
|
}
|
|
|
|
func TestGetSubscriptionEnablesCheckoutWhenPaddleConfigured(t *testing.T) {
|
|
service := NewService(testConfig(), db.NewMemoryRepository())
|
|
|
|
snapshot, err := service.GetSubscription(context.Background(), domain.Principal{
|
|
Subject: "demo-owner",
|
|
Email: "owner@bookra.dev",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("get subscription: %v", err)
|
|
}
|
|
if !snapshot.CheckoutURLAvailable {
|
|
t.Fatal("expected checkout available when paddle is configured")
|
|
}
|
|
if !snapshot.PortalAvailable {
|
|
t.Fatal("expected portal available when customer exists")
|
|
}
|
|
}
|
|
|
|
func TestCreatePortalSessionRequiresCustomer(t *testing.T) {
|
|
repo := db.NewMemoryRepository()
|
|
membership, err := repo.GetTenantMembershipByUserID(context.Background(), "demo-owner")
|
|
if err != nil {
|
|
t.Fatalf("get membership: %v", err)
|
|
}
|
|
if err := repo.UpdateTenantBillingCustomerID(context.Background(), membership.Tenant.ID, ""); err != nil {
|
|
t.Fatalf("clear billing customer: %v", err)
|
|
}
|
|
service := NewService(testConfig(), repo)
|
|
|
|
_, err = service.CreatePortalSession(context.Background(), domain.Principal{
|
|
Subject: "demo-owner",
|
|
Email: "owner@bookra.dev",
|
|
})
|
|
if err != ErrBillingCustomerMissing {
|
|
t.Fatalf("expected ErrBillingCustomerMissing, got %v", err)
|
|
}
|
|
}
|