Files
Tomas Dvorak 7d3e3448cf
CI / Frontend (push) Successful in 9m50s
CI / Go - apps/auth-service (push) Failing after 4s
CI / Go - apps/backend (push) Successful in 10m18s
CI / Docker publish - auth-service (push) Has been skipped
CI / Docker publish - backend (push) Has been skipped
feat(sms): implement SMS messaging and metered billing
Implement a complete SMS messaging system including:
- Integration with SMS Manager.cz API for sending messages.
- Metered billing via Stripe using monthly aggregate invoice items.
- Backend services for managing SMS settings, usage logging, and monthly reporting.
- Database migrations for tenant settings, usage logs, and monthly reports.
- Frontend dashboard components for SMS configuration, usage tracking, and history.
- Support for customer phone numbers in the booking flow.

Includes new migrations, backend services, and frontend UI components.
2026-05-10 11:40:53 +02:00

92 lines
2.5 KiB
Go

package sms
import (
"context"
"testing"
"bookra/apps/backend/internal/config"
"bookra/apps/backend/internal/db"
"bookra/apps/backend/internal/domain"
)
func TestSMSServiceEnabled(t *testing.T) {
cfg := config.Config{SMSManagerAPIKey: "test-key"}
svc := NewService(cfg, db.NewMemoryRepository())
if !svc.Enabled() {
t.Fatal("expected SMS service to be enabled")
}
}
func TestSMSServiceDisabledWithoutKey(t *testing.T) {
cfg := config.Config{}
svc := NewService(cfg, db.NewMemoryRepository())
if svc.Enabled() {
t.Fatal("expected SMS service to be disabled")
}
}
func TestGetSettingsForNewTenant(t *testing.T) {
cfg := config.Config{SMSManagerAPIKey: "test-key"}
repo := db.NewMemoryRepository()
svc := NewService(cfg, repo)
ctx := context.Background()
// Use the default tenant ID from memory repository
settings, err := svc.GetSettings(ctx, "5d6b3551-0a3e-4b86-bdf0-e9df20a47148")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if settings.Enabled {
t.Fatal("expected SMS to be disabled by default")
}
if !settings.Available {
t.Fatal("expected SMS to be available when configured")
}
}
func TestUpdateSettingsRequiresProOrBusiness(t *testing.T) {
cfg := config.Config{SMSManagerAPIKey: "test-key"}
repo := db.NewMemoryRepository()
svc := NewService(cfg, repo)
ctx := context.Background()
// Memory repo tenant is "pro" by default. Change to starter by modifying tenant.
_, err := svc.UpdateSettings(ctx, "5d6b3551-0a3e-4b86-bdf0-e9df20a47148", domain.UpdateSMSSettingsRequest{Enabled: true})
// The memory repo tenant is "pro", so this should succeed
if err != nil {
t.Fatalf("unexpected error for pro tenant: %v", err)
}
}
func TestSendMessageRequiresEnabledSMS(t *testing.T) {
cfg := config.Config{SMSManagerAPIKey: "test-key"}
repo := db.NewMemoryRepository()
svc := NewService(cfg, repo)
ctx := context.Background()
_, err := svc.SendMessage(ctx, "5d6b3551-0a3e-4b86-bdf0-e9df20a47148", domain.SendSMSRequest{To: "+420777123456", Body: "Hello"})
if err != ErrSMSNotEnabled {
t.Fatalf("expected ErrSMSNotEnabled, got: %v", err)
}
}
func TestNormalizePhone(t *testing.T) {
tests := []struct {
input string
expected string
}{
{"+420 777 123 456", "420777123456"},
{"420777123456", "420777123456"},
{"777123456", "420777123456"},
{" 777-123-456 ", "420777123456"},
{"+49 151 12345678", "4915112345678"},
}
for _, tc := range tests {
result := normalizePhone(tc.input)
if result != tc.expected {
t.Errorf("normalizePhone(%q) = %q, want %q", tc.input, result, tc.expected)
}
}
}