Files
descrybe/apps/api/cmd/migrator/legacy_emails_test.go
T
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

153 lines
4.3 KiB
Go

package main
import (
"strings"
"testing"
"github.com/descrybe/descrybe-v2/apps/api/internal/billing"
)
func TestLegacyIDFromSyntheticEmail(t *testing.T) {
t.Parallel()
if got := legacyIDFromSyntheticEmail("user_abc@legacy.local"); got != "user_abc" {
t.Fatalf("got %q", got)
}
if got := legacyIDFromSyntheticEmail(" User_ABC@Legacy.Local "); got != "user_abc" {
t.Fatalf("got %q", got)
}
if got := legacyIDFromSyntheticEmail("real@example.com"); got != "" {
t.Fatalf("want empty, got %q", got)
}
}
func TestParseEmailPatchJSONMap(t *testing.T) {
t.Parallel()
m, err := parseEmailPatchJSON([]byte(`{"user_1":"A@Example.COM","user_2":""}`))
if err != nil {
t.Fatal(err)
}
if m["user_1"] != "a@example.com" {
t.Fatalf("got %#v", m)
}
if _, ok := m["user_2"]; ok {
t.Fatal("empty emails must be dropped")
}
}
func TestParseEmailPatchJSONInventoryEmails(t *testing.T) {
t.Parallel()
raw := []byte(`{
"version": 1,
"emails": {"user_x":"x@example.com"},
"users": [{"legacy_user_id":"user_x","email":"user_x@legacy.local"}]
}`)
m, err := parseEmailPatchJSON(raw)
if err != nil {
t.Fatal(err)
}
if m["user_x"] != "x@example.com" {
t.Fatalf("got %#v", m)
}
}
func TestParseEmailPatchJSONArrayClerkish(t *testing.T) {
t.Parallel()
raw := []byte(`[
{"id":"user_a","primary_email_address":"a@ex.com"},
{"id":"user_b","email_addresses":[{"email_address":"b@ex.com","primary":true}]}
]`)
m, err := parseEmailPatchJSON(raw)
if err != nil {
t.Fatal(err)
}
if m["user_a"] != "a@ex.com" || m["user_b"] != "b@ex.com" {
t.Fatalf("got %#v", m)
}
}
func TestParseEmailPatchCSV(t *testing.T) {
t.Parallel()
m, err := parseEmailPatchCSV([]byte("id,primary_email_address\nuser_c,C@Ex.COM\n"))
if err != nil {
t.Fatal(err)
}
if m["user_c"] != "c@ex.com" {
t.Fatalf("got %#v", m)
}
}
func TestPlanEmailPatchesSafety(t *testing.T) {
t.Parallel()
rows := []legacyEmailRow{
{ID: "u1", Email: "user_1@legacy.local", LegacyUserID: "user_1", A1Member: true},
{ID: "u2", Email: "a1-primary@descrybe.local", LegacyUserID: "user_live", A1Member: true},
{ID: "u3", Email: "user_3@legacy.local", LegacyUserID: "user_3"},
{ID: "u4", Email: "user_4@legacy.local", LegacyUserID: "user_4"},
{ID: "u5", Email: "user_5@legacy.local", LegacyUserID: "user_5"},
}
byLegacy := map[string]string{
"user_1": "real1@example.com",
"user_live": "should-not-apply@example.com",
"user_3": "user_3@legacy.local",
"user_4": "taken@example.com",
"user_5": "real5@example.com",
"user_missing": "ghost@example.com",
}
occupied := map[string]string{
"user_1@legacy.local": "u1",
"a1-primary@descrybe.local": "u2",
"user_3@legacy.local": "u3",
"user_4@legacy.local": "u4",
"user_5@legacy.local": "u5",
"taken@example.com": "other",
}
plan := planEmailPatches(rows, byLegacy, occupied)
if len(plan.Apply) != 1 || plan.Apply[0].UserID != "u5" || plan.Apply[0].ToEmail != "real5@example.com" {
t.Fatalf("apply=%#v", plan.Apply)
}
if plan.Apply[0].A1Member {
t.Fatal("apply list must never include a1_member=true")
}
reasons := map[string]bool{}
for _, s := range plan.Skips {
reasons[s.Reason] = true
if s.UserID == "u1" && s.Reason != "a1_member" {
t.Fatalf("A1 synthetic email must skip as a1_member, skip=%#v", s)
}
if s.UserID == "u2" && s.Reason != "a1_member" {
t.Fatalf("live A1 email must skip as a1_member, skip=%#v", s)
}
}
for _, want := range []string{
"a1_member",
"target_still_synthetic",
"target_email_owned_by_other",
"no_synthetic_user_for_legacy_id",
} {
if !reasons[want] {
t.Fatalf("missing skip reason %q in %#v", want, plan.Skips)
}
}
}
func TestPlanEmailPatchesEmptyMap(t *testing.T) {
t.Parallel()
plan := planEmailPatches(nil, nil, nil)
if len(plan.Skips) != 1 || !strings.Contains(plan.Skips[0].Reason, "empty") {
t.Fatalf("got %#v", plan.Skips)
}
}
func TestRowIsA1Member(t *testing.T) {
t.Parallel()
if !rowIsA1Member(legacyEmailRow{LegacyCompanyIDs: []string{billing.A1LegacyCompanyID}}) {
t.Fatal("expected A1 by legacy company id")
}
if !rowIsA1Member(legacyEmailRow{Companies: []string{"A1 Slovenija"}}) {
t.Fatal("expected A1 by name")
}
if rowIsA1Member(legacyEmailRow{Companies: []string{"Acme"}}) {
t.Fatal("Acme is not A1")
}
}