package repository_test import ( "codeword/internal/models" "codeword/internal/repository" "context" "fmt" "github.com/stretchr/testify/require" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "log" "strconv" "testing" "time" "github.com/pioz/faker" "github.com/stretchr/testify/assert" ) const mongoURI = "mongodb://test:test@127.0.0.1:27020/?authMechanism=SCRAM-SHA-256&authSource=admin&directConnection=true" // codeword unit tests func TestFindByEmail(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() client, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) if err != nil { log.Fatalf("Failed to connect to MongoDB: %v", err) } defer func() { if err := client.Disconnect(ctx); err != nil { log.Fatalf("Failed to disconnect MongoDB client: %v", err) } }() if err := client.Ping(ctx, nil); err != nil { log.Fatalf("Failed to ping MongoDB: %v", err) } db := client.Database("admin") userRepo := repository.NewUserRepository(repository.Deps{Rdb: nil, Mdb: db.Collection("users")}) t.Run("FindByEmail - existing user", func(t *testing.T) { user, err := userRepo.FindByEmail(ctx, "admin") assert.NoError(t, err) assert.NotNil(t, user) fmt.Println(user.Email) assert.Equal(t, "admin", user.Login) }) t.Run("FindByEmail - non-existing user", func(t *testing.T) { user, err := userRepo.FindByEmail(ctx, "neadmin") assert.NoError(t, err) assert.Nil(t, user) }) } func TestStoreRecoveryRecord(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) require.NoError(t, err) defer func() { _ = mongoClient.Disconnect(ctx) }() database := mongoClient.Database("admin") codeword := database.Collection("codeword") _ = codeword.Drop(ctx) userRepo := repository.NewCodewordRepository(repository.Deps{Rdb: nil, Mdb: codeword}) for i := 0; i < 10; i++ { userID := faker.String() email := faker.Email() key := "test_recovery_key" id, err := userRepo.StoreRecoveryRecord(ctx, models.StoreRecDeps{UserID: userID, Email: email, Key: key, Url: "def.url"}) assert.NoError(t, err) fmt.Println(id) var storedRecord models.RestoreRequest err = codeword.FindOne(ctx, bson.M{"user_id": userID}).Decode(&storedRecord) assert.NoError(t, err) assert.Equal(t, email, storedRecord.Email) assert.Equal(t, key, storedRecord.Sign) } _ = database.Drop(ctx) } func TestGetRecoveryRecord(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) require.NoError(t, err) defer func() { _ = mongoClient.Disconnect(ctx) }() database := mongoClient.Database("admin") codeword := database.Collection("codeword") _ = codeword.Drop(ctx) userRepo := repository.NewCodewordRepository(repository.Deps{Rdb: nil, Mdb: codeword}) ID := primitive.NewObjectID() userID := "6597babdd1ba7e2dbd32d7e3" email := "test@mail.ru" key := "test_recovery_key" record := models.RestoreRequest{ ID: ID, UserID: userID, Email: email, Sign: key, SignUrl: "def.url", SignID: key + userID, CreatedAt: time.Now(), } _, err = codeword.InsertOne(ctx, record) assert.NoError(t, err) result, err := userRepo.GetRecoveryRecord(ctx, key+userID) assert.NoError(t, err) assert.Equal(t, userID, result.UserID) assert.Equal(t, email, result.Email) assert.Equal(t, key, result.Sign) _ = database.Drop(ctx) } // promoCode unit tests func TestInitPromoCodeIndexes(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) require.NoError(t, err) defer func() { _ = mongoClient.Disconnect(ctx) }() database := mongoClient.Database("admin") promoCode := database.Collection("promoCode") err = repository.InitPromoCodeIndexes(ctx, promoCode) assert.NoError(t, err) } func TestCreatePromoCode(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) require.NoError(t, err) defer func() { _ = mongoClient.Disconnect(ctx) }() database := mongoClient.Database("admin") promoCode := database.Collection("promoCode") _ = promoCode.Drop(ctx) userRepo := repository.NewPromoCodeRepository(promoCode) err = repository.InitPromoCodeIndexes(ctx, promoCode) assert.NoError(t, err) t.Run("CreatePromoCode - success", func(t *testing.T) { req := &models.PromoCode{ Codeword: "test_codeword", Description: faker.String(), Greetings: faker.String(), DueTo: 1737280065, ActivationCount: 100, } createdPromoCode, err := userRepo.CreatePromoCode(ctx, req) assert.NoError(t, err) assert.NotNil(t, createdPromoCode) assert.Equal(t, "test_codeword", createdPromoCode.Codeword) }) t.Run("CreatePromoCode - duplicate codeword", func(t *testing.T) { req := &models.PromoCode{ Codeword: "test_codeword", Description: faker.String(), Greetings: faker.String(), DueTo: 1737280065, ActivationCount: 100, } _, err := userRepo.CreatePromoCode(ctx, req) assert.Error(t, err) }) } func TestEditPromoCode(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) require.NoError(t, err) defer func() { _ = mongoClient.Disconnect(ctx) }() database := mongoClient.Database("admin") promoCode := database.Collection("promoCode") _ = promoCode.Drop(ctx) userRepo := repository.NewPromoCodeRepository(promoCode) err = repository.InitPromoCodeIndexes(ctx, promoCode) assert.NoError(t, err) req := &models.PromoCode{ Codeword: "test_codeword", Description: faker.String(), Greetings: faker.String(), DueTo: 1737280065, ActivationCount: 100, } createdPromoCode, err := userRepo.CreatePromoCode(ctx, req) require.NoError(t, err) newDescription := "New Description" t.Run("EditPromoCode - success", func(t *testing.T) { editReq := &models.ReqEditPromoCode{ ID: createdPromoCode.ID.Hex(), Description: &newDescription, } editedPromoCode, err := userRepo.EditPromoCode(ctx, editReq) assert.NoError(t, err) assert.NotNil(t, editedPromoCode) assert.Equal(t, "New Description", editedPromoCode.Description) }) t.Run("EditPromoCode - promo code not found", func(t *testing.T) { nonExistingID := primitive.NewObjectID().Hex() editReq := &models.ReqEditPromoCode{ ID: nonExistingID, } _, err := userRepo.EditPromoCode(ctx, editReq) assert.Error(t, err) }) } func TestGetPromoCodeByID(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) require.NoError(t, err) defer func() { _ = mongoClient.Disconnect(ctx) }() database := mongoClient.Database("admin") promoCode := database.Collection("promoCode") _ = promoCode.Drop(ctx) userRepo := repository.NewPromoCodeRepository(promoCode) err = repository.InitPromoCodeIndexes(ctx, promoCode) assert.NoError(t, err) req := &models.PromoCode{ Codeword: "test_codeword", Description: faker.String(), Greetings: faker.String(), DueTo: 1737280065, ActivationCount: 100, } createdPromoCode, err := userRepo.CreatePromoCode(ctx, req) require.NoError(t, err) t.Run("GetPromoCodeByID - success", func(t *testing.T) { result, err := userRepo.GetPromoCodeByID(ctx, createdPromoCode.ID) assert.NoError(t, err) assert.NotNil(t, result) assert.Equal(t, createdPromoCode.Codeword, result.Codeword) }) t.Run("GetPromoCodeByID - promo code not found", func(t *testing.T) { nonExistingID := primitive.NewObjectID() _, err := userRepo.GetPromoCodeByID(ctx, nonExistingID) assert.Error(t, err) }) } func TestGetPromoCodesList(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) require.NoError(t, err) defer func() { _ = mongoClient.Disconnect(ctx) }() database := mongoClient.Database("admin") promoCode := database.Collection("promoCode") _ = promoCode.Drop(ctx) userRepo := repository.NewPromoCodeRepository(promoCode) err = repository.InitPromoCodeIndexes(ctx, promoCode) assert.NoError(t, err) for i := 0; i < 1111; i++ { req := &models.PromoCode{ Codeword: "test" + faker.String() + strconv.Itoa(i), Description: faker.String(), Greetings: faker.String(), DueTo: 1737280065, ActivationCount: 100, Delete: faker.Bool(), Outdated: faker.Bool(), OffLimit: faker.Bool(), } createdPromoCode, err := userRepo.CreatePromoCode(ctx, req) assert.NoError(t, err) assert.NotNil(t, createdPromoCode) } t.Run("GetPromoCodesList - true", func(t *testing.T) { filter := models.GetPromoCodesListReqFilter{ Text: "test", Active: true, } req := &models.GetPromoCodesListReq{ Page: 0, Limit: 10, Filter: filter, } promoCodes, count, err := userRepo.GetPromoCodesList(ctx, req) assert.NoError(t, err) assert.NotNil(t, promoCodes) assert.True(t, count >= 0) }) t.Run("GetPromoCodesList - false", func(t *testing.T) { filter := models.GetPromoCodesListReqFilter{ Text: "test", Active: false, } req := &models.GetPromoCodesListReq{ Page: 0, Limit: 10, Filter: filter, } promoCodes, count, err := userRepo.GetPromoCodesList(ctx, req) assert.NoError(t, err) assert.NotNil(t, promoCodes) assert.True(t, count >= 0) }) } func TestActivatePromo(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) require.NoError(t, err) defer func() { _ = mongoClient.Disconnect(ctx) }() database := mongoClient.Database("admin") promoCode := database.Collection("promoCode") _ = promoCode.Drop(ctx) userRepo := repository.NewPromoCodeRepository(promoCode) err = repository.InitPromoCodeIndexes(ctx, promoCode) assert.NoError(t, err) req := &models.PromoCode{ Codeword: "test_codeword", Description: faker.String(), Greetings: faker.String(), DueTo: 1737280065, ActivationCount: 100, } createdPromoCode, err := userRepo.CreatePromoCode(ctx, req) assert.NoError(t, err) assert.NotNil(t, createdPromoCode) xid := "test_xid" err = userRepo.AddFastLink(ctx, createdPromoCode.ID, xid) assert.NoError(t, err) t.Run("ActivatePromo Codeword - success", func(t *testing.T) { req := &models.ActivateReq{ UserID: "6597babdd1ba7e2dbd32d7e3", Codeword: "test_codeword", } activatedPromoCode, err := userRepo.ActivatePromo(ctx, req) assert.NoError(t, err) assert.NotNil(t, activatedPromoCode) }) t.Run("ActivatePromo FastLink - success", func(t *testing.T) { req := &models.ActivateReq{ UserID: "6597babdd1ba7e2dbd32d7e3", FastLink: "test_xid", } activatedPromoCode, err := userRepo.ActivatePromo(ctx, req) assert.NoError(t, err) assert.NotNil(t, activatedPromoCode) }) t.Run("ActivatePromo - promo code not found", func(t *testing.T) { req := &models.ActivateReq{ UserID: "6597babdd1ba7e2dbd32d7e3", Codeword: "non_existing_codeword", } _, err := userRepo.ActivatePromo(ctx, req) assert.Error(t, err) }) } func TestDeletePromoCode(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) require.NoError(t, err) defer func() { _ = mongoClient.Disconnect(ctx) }() database := mongoClient.Database("admin") promoCode := database.Collection("promoCode") _ = promoCode.Drop(ctx) userRepo := repository.NewPromoCodeRepository(promoCode) err = repository.InitPromoCodeIndexes(ctx, promoCode) assert.NoError(t, err) req := &models.PromoCode{ Codeword: "test_codeword", Description: faker.String(), Greetings: faker.String(), DueTo: 1737280065, ActivationCount: 100, } createdPromoCode, err := userRepo.CreatePromoCode(ctx, req) assert.NoError(t, err) assert.NotNil(t, createdPromoCode) t.Run("DeletePromoCode - success", func(t *testing.T) { err := userRepo.DeletePromoCode(ctx, createdPromoCode.ID.Hex()) assert.NoError(t, err) }) t.Run("DeletePromoCode - promo code not found", func(t *testing.T) { nonExistingID := primitive.NewObjectID().Hex() err := userRepo.DeletePromoCode(ctx, nonExistingID) assert.Error(t, err) }) } func TestAddFastLink(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) require.NoError(t, err) defer func() { _ = mongoClient.Disconnect(ctx) }() database := mongoClient.Database("admin") promoCode := database.Collection("promoCode") _ = promoCode.Drop(ctx) userRepo := repository.NewPromoCodeRepository(promoCode) err = repository.InitPromoCodeIndexes(ctx, promoCode) assert.NoError(t, err) req := &models.PromoCode{ Codeword: "test_codeword", Description: faker.String(), Greetings: faker.String(), DueTo: 1737280065, ActivationCount: 100, } createdPromoCode, err := userRepo.CreatePromoCode(ctx, req) assert.NoError(t, err) assert.NotNil(t, createdPromoCode) t.Run("AddFastLink - success", func(t *testing.T) { xid := "test_xid" err := userRepo.AddFastLink(ctx, createdPromoCode.ID, xid) assert.NoError(t, err) }) t.Run("AddFastLink - promo code not found", func(t *testing.T) { nonExistingID := primitive.NewObjectID() xid := "test_xid" err := userRepo.AddFastLink(ctx, nonExistingID, xid) assert.Error(t, err) }) }