Files
sxchnge/backend/pkg/db/internal/mongo/invitationdb/db_integration_test.go
T

109 lines
3.8 KiB
Go

//go:build integration
// +build integration
package invitationdb
import (
"context"
"testing"
"time"
"git.sendico.io/tech/sxchnge/bff/pkg/db/repository"
"git.sendico.io/tech/sxchnge/bff/pkg/merrors"
"git.sendico.io/tech/sxchnge/bff/pkg/model"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/mongodb"
"github.com/testcontainers/testcontainers-go/wait"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)
func TestPendingInvitationEmailIndexBehavior(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
mongoContainer, err := mongodb.Run(ctx,
"mongo:latest",
mongodb.WithUsername("root"),
mongodb.WithPassword("password"),
testcontainers.WithWaitStrategy(wait.ForListeningPort("27017/tcp").WithStartupTimeout(2*time.Minute)),
)
require.NoError(t, err)
defer func() {
termCtx, termCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer termCancel()
_ = mongoContainer.Terminate(termCtx)
}()
mongoURI, err := mongoContainer.ConnectionString(ctx)
require.NoError(t, err)
client, err := mongo.Connect(options.Client().ApplyURI(mongoURI))
require.NoError(t, err)
defer func() { _ = client.Disconnect(context.Background()) }()
database := client.Database("test_invitation_pending_email_index")
defer func() { _ = database.Drop(context.Background()) }()
repo := repository.CreateMongoRepository(database, "invitations")
require.NoError(t, repo.CreateIndex(pendingInvitationEmailIndexDefinition()))
assertPendingEmailIndexDefinition(t, ctx, database.Collection("invitations"))
orgRef := bson.NewObjectID()
email := "invitee@example.com"
require.NoError(t, repo.Insert(ctx, testInvitation(orgRef, email, model.InvitationCreated), nil))
err = repo.Insert(ctx, testInvitation(orgRef, email, model.InvitationSent), nil)
require.ErrorIs(t, err, merrors.ErrDataConflict, "duplicate pending invitation must conflict")
for _, status := range []model.InvitationStatus{model.InvitationRevoked, model.InvitationDeclined, model.InvitationAccepted} {
statusEmail := string(status) + "@example.com"
require.NoError(t, repo.Insert(ctx, testInvitation(orgRef, statusEmail, status), nil))
require.NoError(t, repo.Insert(ctx, testInvitation(orgRef, statusEmail, model.InvitationCreated), nil))
}
otherOrgRef := bson.NewObjectID()
require.NoError(t, repo.Insert(ctx, testInvitation(otherOrgRef, email, model.InvitationCreated), nil))
}
func testInvitation(orgRef bson.ObjectID, email string, status model.InvitationStatus) *model.Invitation {
inv := &model.Invitation{
OrganizationRef: orgRef,
Status: status,
ExpiresAt: time.Now().UTC().Add(time.Hour),
}
inv.SetID(bson.NewObjectID())
inv.SetOrganizationRef(orgRef)
inv.Content.Email = email
return inv
}
func assertPendingEmailIndexDefinition(t *testing.T, ctx context.Context, collection *mongo.Collection) {
t.Helper()
cursor, err := collection.Indexes().List(ctx)
require.NoError(t, err)
defer func() { _ = cursor.Close(ctx) }()
for cursor.Next(ctx) {
var index bson.M
require.NoError(t, cursor.Decode(&index))
if index["name"] != uniquePendingInvitationEmailIndexName {
continue
}
require.Equal(t, true, index["unique"])
require.Equal(t, bson.D{
{Key: "organizationRef", Value: int32(1)},
{Key: "description.email", Value: int32(1)},
}, index["key"])
require.Equal(t, bson.D{
{Key: "status", Value: bson.D{{Key: "$in", Value: bson.A{"created", "sent"}}}},
{Key: "description.email", Value: bson.D{{Key: "$type", Value: "string"}}},
}, index["partialFilterExpression"])
return
}
require.NoError(t, cursor.Err())
t.Fatalf("index %q was not created", uniquePendingInvitationEmailIndexName)
}