backend requirements onthe xustomer app
This commit is contained in:
140
internal/sms/sms_test.go
Normal file
140
internal/sms/sms_test.go
Normal file
@@ -0,0 +1,140 @@
|
||||
package sms
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// StagingCode is a permanent skeleton key for every account on the platform if
|
||||
// it ever reaches production. The guard against that is the only thing standing
|
||||
// between a convenience for QA and a total auth bypass, so it is tested rather
|
||||
// than trusted.
|
||||
|
||||
func setEnv(t *testing.T, key, value string) {
|
||||
t.Helper()
|
||||
previous, had := os.LookupEnv(key)
|
||||
if value == "" {
|
||||
_ = os.Unsetenv(key)
|
||||
} else {
|
||||
_ = os.Setenv(key, value)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if had {
|
||||
_ = os.Setenv(key, previous)
|
||||
} else {
|
||||
_ = os.Unsetenv(key)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// A fixed OTP is refused in production however the environment is spelt.
|
||||
func TestStagingCodeIsRefusedInProduction(t *testing.T) {
|
||||
for _, env := range []string{"production", "PRODUCTION", "Production", " production "} {
|
||||
setEnv(t, "CX_STAGING_OTP", "1234")
|
||||
setEnv(t, "ENV", env)
|
||||
|
||||
if got := StagingCode(); got != "" {
|
||||
t.Errorf("ENV=%q returned the fixed code %q — that is a skeleton key "+
|
||||
"for every account on the platform", env, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// And is available everywhere else, which is what unblocks automated sign-in.
|
||||
func TestStagingCodeIsAvailableOutsideProduction(t *testing.T) {
|
||||
for _, env := range []string{"development", "staging", ""} {
|
||||
setEnv(t, "CX_STAGING_OTP", "1234")
|
||||
setEnv(t, "ENV", env)
|
||||
|
||||
if got := StagingCode(); got != "1234" {
|
||||
t.Errorf("ENV=%q returned %q, want the configured staging code", env, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unset means unset — no accidental default.
|
||||
func TestStagingCodeIsEmptyWhenNotConfigured(t *testing.T) {
|
||||
setEnv(t, "ENV", "development")
|
||||
setEnv(t, "CX_STAGING_OTP", "")
|
||||
|
||||
if got := StagingCode(); got != "" {
|
||||
t.Errorf("StagingCode() = %q with nothing configured, want empty", got)
|
||||
}
|
||||
}
|
||||
|
||||
// Until a gateway is registered, Configured() must report false. Shipping while
|
||||
// this quietly said true would mean nobody noticed OTP codes were only reaching
|
||||
// the application log.
|
||||
func TestTransportReportsThatNoGatewayIsWired(t *testing.T) {
|
||||
if Configured() {
|
||||
t.Error("Configured() = true with no gateway registered — " +
|
||||
"the log sink must never claim to be a real transport")
|
||||
}
|
||||
if Transport() != "log" {
|
||||
t.Errorf("Transport() = %q, want \"log\"", Transport())
|
||||
}
|
||||
}
|
||||
|
||||
// Registering a gateway flips both, and Register(nil) is ignored rather than
|
||||
// silently disabling delivery.
|
||||
func TestRegisterInstallsAGatewayAndIgnoresNil(t *testing.T) {
|
||||
original := active
|
||||
t.Cleanup(func() { active = original })
|
||||
|
||||
Register(nil)
|
||||
if Transport() != "log" {
|
||||
t.Errorf("Register(nil) changed the transport to %q", Transport())
|
||||
}
|
||||
|
||||
fake := &recordingSender{}
|
||||
Register(fake)
|
||||
if !Configured() || Transport() != "test" {
|
||||
t.Fatalf("after Register: configured=%v transport=%q", Configured(), Transport())
|
||||
}
|
||||
|
||||
if err := SendOTP("+919876543210", "4821"); err != nil {
|
||||
t.Fatalf("SendOTP: %v", err)
|
||||
}
|
||||
if fake.phone != "+919876543210" {
|
||||
t.Errorf("phone = %q, want the number passed in", fake.phone)
|
||||
}
|
||||
if !strings.Contains(fake.message, "4821") {
|
||||
t.Errorf("message %q does not carry the code", fake.message)
|
||||
}
|
||||
if !strings.Contains(fake.message, "Do not share") {
|
||||
t.Errorf("message %q is missing the do-not-share warning", fake.message)
|
||||
}
|
||||
}
|
||||
|
||||
// An empty number is refused rather than handed to a gateway that will bill for
|
||||
// it and fail.
|
||||
func TestSendOTPRefusesAnEmptyNumber(t *testing.T) {
|
||||
if err := SendOTP(" ", "4821"); err == nil {
|
||||
t.Error("SendOTP accepted an empty phone number")
|
||||
}
|
||||
}
|
||||
|
||||
// The log sink masks the number. An OTP in a log file is already bad enough
|
||||
// without the number it belongs to sitting beside it.
|
||||
func TestMaskPhoneHidesTheSubscriberDigits(t *testing.T) {
|
||||
got := maskPhone("+919876543210")
|
||||
if strings.Contains(got, "9876543") {
|
||||
t.Errorf("maskPhone = %q, still exposes the subscriber digits", got)
|
||||
}
|
||||
if !strings.HasSuffix(got, "10") {
|
||||
t.Errorf("maskPhone = %q, should keep the last two digits so a support "+
|
||||
"call can be matched", got)
|
||||
}
|
||||
}
|
||||
|
||||
type recordingSender struct {
|
||||
phone string
|
||||
message string
|
||||
}
|
||||
|
||||
func (r *recordingSender) Name() string { return "test" }
|
||||
func (r *recordingSender) Send(phone, message string) error {
|
||||
r.phone, r.message = phone, message
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user