177 lines
5.0 KiB
Go
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)
|
|
}
|
|
}
|