356bf1a5ba
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 1m3s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m40s
Add an exact (strict) email filter to the /users list (UserFilter.EmailExact → a kind='email' identity match) with a search input, and an 'Erase email' action on the user card that deletes the bound email identity and its pending confirmations, freeing the address. It refuses to remove the account's only identity (ErrLastIdentity), which would leave it unreachable. Integration tests for both.
84 lines
2.4 KiB
Go
84 lines
2.4 KiB
Go
//go:build integration
|
|
|
|
package inttest
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"scrabble/backend/internal/account"
|
|
)
|
|
|
|
// TestRemoveEmailIdentity erases an account's email identity but refuses when the
|
|
// email is the account's only identity (which would leave it unreachable).
|
|
func TestRemoveEmailIdentity(t *testing.T) {
|
|
ctx := context.Background()
|
|
store := account.NewStore(testDB)
|
|
|
|
// Email is the only identity → refuse.
|
|
solo, err := store.ProvisionEmail(ctx, "solo-"+uuid.NewString()+"@example.com", "", "en")
|
|
if err != nil {
|
|
t.Fatalf("provision email: %v", err)
|
|
}
|
|
if err := store.RemoveEmailIdentity(ctx, solo.ID); !errors.Is(err, account.ErrLastIdentity) {
|
|
t.Fatalf("remove last identity = %v, want ErrLastIdentity", err)
|
|
}
|
|
|
|
// Telegram + email → erase the email, keep Telegram.
|
|
tg, err := store.ProvisionByIdentity(ctx, account.KindTelegram, "tg-"+uuid.NewString())
|
|
if err != nil {
|
|
t.Fatalf("provision telegram: %v", err)
|
|
}
|
|
if err := store.AttachIdentity(ctx, tg.ID, account.KindEmail, "dual-"+uuid.NewString()+"@example.com", true); err != nil {
|
|
t.Fatalf("attach email: %v", err)
|
|
}
|
|
if err := store.RemoveEmailIdentity(ctx, tg.ID); err != nil {
|
|
t.Fatalf("remove email: %v", err)
|
|
}
|
|
ids, err := store.Identities(ctx, tg.ID)
|
|
if err != nil {
|
|
t.Fatalf("identities: %v", err)
|
|
}
|
|
if len(ids) != 1 || ids[0].Kind != account.KindTelegram {
|
|
t.Errorf("identities after erase = %+v, want only telegram", ids)
|
|
}
|
|
}
|
|
|
|
// TestListUsersEmailExact matches accounts strictly (exactly) by their email identity.
|
|
func TestListUsersEmailExact(t *testing.T) {
|
|
ctx := context.Background()
|
|
store := account.NewStore(testDB)
|
|
email := "find-" + uuid.NewString() + "@example.com"
|
|
acc, err := store.ProvisionEmail(ctx, email, "", "en")
|
|
if err != nil {
|
|
t.Fatalf("provision: %v", err)
|
|
}
|
|
|
|
items, err := store.ListUsers(ctx, account.UserFilter{EmailExact: email}, 50, 0)
|
|
if err != nil {
|
|
t.Fatalf("list: %v", err)
|
|
}
|
|
found := false
|
|
for _, it := range items {
|
|
if it.ID == acc.ID {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Error("the exact email filter did not find the account")
|
|
}
|
|
|
|
other, err := store.ListUsers(ctx, account.UserFilter{EmailExact: "nope-" + uuid.NewString() + "@example.com"}, 50, 0)
|
|
if err != nil {
|
|
t.Fatalf("list (no match): %v", err)
|
|
}
|
|
for _, it := range other {
|
|
if it.ID == acc.ID {
|
|
t.Error("a non-matching email filter must not return the account")
|
|
}
|
|
}
|
|
}
|