Files
warmbly/internal/models/warmup_routing_test.go
T
Matthew Meszaros 43d24bc3d7 feat: customer-defined warmup routing rules on premium pool
new warmup_routing_rules table + repo + REST endpoints under /warmup/
routing. each rule matches a (sender, recipient) pair by domain, TLD,
provider bucket, or any wildcard, with a weight multiplier on the
selector. weight > 1 prefers the pairing, < 1 discourages, 0 excludes.
rules are evaluated in priority order (ascending) and combined with the
existing domain-diversity weighting. example use case: a customer can
say 'send Gmail-recipient warmup only from Google-classified senders'
with one rule; or 'never send to acme.com from this org's mailboxes'
with weight=0. premium pool only — free pool ignores rules.
2026-05-25 15:42:50 +00:00

91 lines
2.5 KiB
Go

package models
import "testing"
func TestClassifyProvider(t *testing.T) {
tests := []struct {
domain string
want WarmupProvider
}{
{"gmail.com", ProviderGoogle},
{"googlemail.com", ProviderGoogle},
{"outlook.com", ProviderMicrosoft},
{"hotmail.com", ProviderMicrosoft},
{"yahoo.com", ProviderYahoo},
{"icloud.com", ProviderApple},
{"proton.me", ProviderProton},
{"zoho.com", ProviderZoho},
{"someweirddomain.io", ProviderCustom},
{"", ProviderCustom},
{"GMAIL.COM", ProviderGoogle},
}
for _, tt := range tests {
if got := ClassifyProvider(tt.domain); got != tt.want {
t.Errorf("ClassifyProvider(%q) = %v, want %v", tt.domain, got, tt.want)
}
}
}
func TestWarmupRoutingRule_Matches_ProviderMatch(t *testing.T) {
rule := &WarmupRoutingRule{
Enabled: true,
SenderMatchType: WarmupMatchProvider,
SenderMatchValue: "google",
RecipientMatchType: WarmupMatchProvider,
RecipientMatchValue: "google",
Weight: 2.5,
}
if !rule.Matches("alice@gmail.com", "bob@googlemail.com") {
t.Error("expected match for two Google addresses")
}
if rule.Matches("alice@gmail.com", "bob@outlook.com") {
t.Error("expected no match for Google sender → Microsoft recipient")
}
}
func TestWarmupRoutingRule_Matches_DomainAny(t *testing.T) {
rule := &WarmupRoutingRule{
Enabled: true,
SenderMatchType: WarmupMatchAny,
RecipientMatchType: WarmupMatchDomain,
RecipientMatchValue: "acme.com",
Weight: 3.0,
}
if !rule.Matches("anyone@anything.io", "lead@acme.com") {
t.Error("expected wildcard sender + domain recipient to match")
}
if rule.Matches("anyone@anything.io", "lead@other.com") {
t.Error("recipient-domain mismatch should not match")
}
}
func TestWarmupRoutingRule_Matches_Disabled(t *testing.T) {
rule := &WarmupRoutingRule{
Enabled: false,
SenderMatchType: WarmupMatchAny,
RecipientMatchType: WarmupMatchAny,
Weight: 10,
}
if rule.Matches("a@b.com", "c@d.com") {
t.Error("disabled rules must not match")
}
}
func TestEmailDomain(t *testing.T) {
if EmailDomain("Alice@Example.COM") != "example.com" {
t.Error("domain should be lowercased")
}
if EmailDomain("noatsign") != "" {
t.Error("expected empty domain for malformed address")
}
}
func TestEmailTLD(t *testing.T) {
if got := EmailTLD("mail.gmail.com"); got != "com" {
t.Errorf("expected com, got %q", got)
}
if got := EmailTLD("plain"); got != "" {
t.Errorf("expected empty TLD, got %q", got)
}
}