Files
fm_be/internal/repository/mysql/other_person_repo_test.go
2026-07-16 22:16:45 +07:00

177 lines
5.0 KiB
Go

package mysql
import (
"context"
"fmt"
"testing"
"time"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
otherperson "wucher/internal/domain/other_person"
)
func openOtherPersonTestDB(t *testing.T) *gorm.DB {
t.Helper()
dsn := fmt.Sprintf("file:other_person_test_%d?mode=memory&cache=shared", time.Now().UnixNano())
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{
NowFunc: func() time.Time { return time.Now().UTC() },
})
if err != nil {
t.Fatalf("open sqlite: %v", err)
}
if err := db.AutoMigrate(&otherperson.OtherPerson{}); err != nil {
t.Fatalf("auto migrate: %v", err)
}
return db
}
func TestOtherPersonRepositoryUpsertDedup(t *testing.T) {
db := openOtherPersonTestDB(t)
repo := NewOtherPersonRepository(db)
ctx := context.Background()
first := &otherperson.OtherPerson{Name: " Guest One ", MobilePhone: " +43-1 ", Email: " a@x.io "}
if err := repo.Upsert(ctx, first); err != nil {
t.Fatalf("first upsert: %v", err)
}
if len(first.ID) == 0 {
t.Fatalf("expected id set on create")
}
// values should be trimmed on create.
if first.Name != "Guest One" || first.MobilePhone != "+43-1" || first.Email != "a@x.io" {
t.Fatalf("expected trimmed values, got %q/%q/%q", first.Name, first.MobilePhone, first.Email)
}
// Same identity (even with different whitespace) must reuse the existing row, not create a new one.
second := &otherperson.OtherPerson{Name: "Guest One", MobilePhone: "+43-1", Email: "a@x.io"}
if err := repo.Upsert(ctx, second); err != nil {
t.Fatalf("second upsert: %v", err)
}
if string(second.ID) != string(first.ID) {
t.Fatalf("expected reuse of existing id")
}
// A different identity creates a new row.
third := &otherperson.OtherPerson{Name: "Guest Two", MobilePhone: "+43-2", Email: "b@x.io"}
if err := repo.Upsert(ctx, third); err != nil {
t.Fatalf("third upsert: %v", err)
}
if string(third.ID) == string(first.ID) {
t.Fatalf("expected new id for distinct identity")
}
_, total, err := repo.Search(ctx, "", 0, 0)
if err != nil {
t.Fatalf("search: %v", err)
}
if total != 2 {
t.Fatalf("expected 2 master rows, got %d", total)
}
}
func TestOtherPersonRepositorySearch(t *testing.T) {
db := openOtherPersonTestDB(t)
repo := NewOtherPersonRepository(db)
ctx := context.Background()
for _, p := range []*otherperson.OtherPerson{
{Name: "Alice Anderson", MobilePhone: "111", Email: "alice@x.io"},
{Name: "Bob Brown", MobilePhone: "222", Email: "bob@x.io"},
} {
if err := repo.Upsert(ctx, p); err != nil {
t.Fatalf("seed: %v", err)
}
}
rows, total, err := repo.Search(ctx, "alice", 0, 0)
if err != nil {
t.Fatalf("search by name: %v", err)
}
if total != 1 || len(rows) != 1 || rows[0].Name != "Alice Anderson" {
t.Fatalf("expected only Alice, got total=%d rows=%d", total, len(rows))
}
// Match on email fragment too.
rows, total, err = repo.Search(ctx, "bob@", 0, 0)
if err != nil {
t.Fatalf("search by email: %v", err)
}
if total != 1 || len(rows) != 1 || rows[0].Name != "Bob Brown" {
t.Fatalf("expected only Bob, got total=%d rows=%d", total, len(rows))
}
// Empty query returns everything.
_, total, err = repo.Search(ctx, " ", 0, 0)
if err != nil {
t.Fatalf("search empty: %v", err)
}
if total != 2 {
t.Fatalf("expected 2 rows for empty query, got %d", total)
}
}
func TestOtherPersonRepositoryCreateUpdateDelete(t *testing.T) {
db := openOtherPersonTestDB(t)
repo := NewOtherPersonRepository(db)
ctx := context.Background()
row := &otherperson.OtherPerson{Name: " Carol ", MobilePhone: " 333 ", Email: " carol@x.io "}
if err := repo.Create(ctx, row); err != nil {
t.Fatalf("create: %v", err)
}
if len(row.ID) == 0 || row.Name != "Carol" {
t.Fatalf("expected trimmed create with id, got %q id=%d", row.Name, len(row.ID))
}
// FindByIdentity trims and matches.
found, err := repo.FindByIdentity(ctx, "Carol", "333", "carol@x.io")
if err != nil {
t.Fatalf("find identity: %v", err)
}
if found == nil || string(found.ID) != string(row.ID) {
t.Fatalf("expected to find created row")
}
miss, err := repo.FindByIdentity(ctx, "Nobody", "", "")
if err != nil {
t.Fatalf("find miss: %v", err)
}
if miss != nil {
t.Fatalf("expected nil for missing identity")
}
// Update replaces identity fields.
row.Name = "Caroline"
row.Email = "caroline@x.io"
if err := repo.Update(ctx, row); err != nil {
t.Fatalf("update: %v", err)
}
got, err := repo.GetByID(ctx, row.ID)
if err != nil {
t.Fatalf("get after update: %v", err)
}
if got == nil || got.Name != "Caroline" || got.Email != "caroline@x.io" {
t.Fatalf("update not persisted: %+v", got)
}
// Delete soft-deletes: GetByID/Search no longer return it.
if err := repo.Delete(ctx, row.ID, nil); err != nil {
t.Fatalf("delete: %v", err)
}
got, err = repo.GetByID(ctx, row.ID)
if err != nil {
t.Fatalf("get after delete: %v", err)
}
if got != nil {
t.Fatalf("expected soft-deleted row to be hidden")
}
_, total, err := repo.Search(ctx, "", 0, 0)
if err != nil {
t.Fatalf("search after delete: %v", err)
}
if total != 0 {
t.Fatalf("expected 0 live rows after delete, got %d", total)
}
}