diff --git a/internal/controllers/controllers_test.go b/internal/controllers/controllers_test.go index 8da8bfe..1e28b2b 100644 --- a/internal/controllers/controllers_test.go +++ b/internal/controllers/controllers_test.go @@ -98,8 +98,9 @@ func TestSuite(t *testing.T) { var subscriptionRepo repositories.SubscriptionModelsRepositoryInterface = &repositories.SubscriptionModelsRepository{} membershipService := &services.MembershipService{Repo: membershipRepo, SubscriptionRepo: subscriptionRepo} + var licenceRepo repositories.DriversLicenceInterface = &repositories.DriversLicenceRepository{} var userRepo repositories.UserRepositoryInterface = &repositories.UserRepository{} - userService := &services.UserService{Repo: userRepo} + userService := &services.UserService{Repo: userRepo, Licences: licenceRepo} Uc = &UserController{Service: userService, EmailService: emailService, ConsentService: consentService, BankAccountService: bankAccountService, MembershipService: membershipService} Mc = &MembershipController{Service: *membershipService} @@ -133,9 +134,9 @@ func TestSuite(t *testing.T) { log.Fatalf("Failed to stop SMTP Mockup Server: %#v", err) } - if err := deleteTestDB("test.db"); err != nil { - log.Fatalf("Failed to tear down DB: %#v", err) - } + // if err := deleteTestDB("test.db"); err != nil { + // log.Fatalf("Failed to tear down DB: %#v", err) + // } } func initSubscriptionPlans() error { @@ -221,6 +222,7 @@ func getBaseUser() models.User { Phone: "01738484993", BankAccount: models.BankAccount{IBAN: "DE89370400440532013000"}, Membership: models.Membership{SubscriptionModel: models.SubscriptionModel{Name: "Basic"}}, + DriversLicence: models.DriversLicence{}, ProfilePicture: "", Password: "password123", Company: "", diff --git a/internal/controllers/user_controller_test.go b/internal/controllers/user_controller_test.go index 2132c13..9ba700e 100644 --- a/internal/controllers/user_controller_test.go +++ b/internal/controllers/user_controller_test.go @@ -22,6 +22,7 @@ import ( "GoMembership/internal/constants" "GoMembership/internal/middlewares" "GoMembership/internal/models" + "GoMembership/internal/repositories" "GoMembership/internal/utils" "GoMembership/pkg/logger" @@ -285,7 +286,7 @@ func testCurrentUserHandler(t *testing.T, loginEmail string, loginCookie http.Co for _, tt := range tests { logger.Error.Print("==============================================================") - logger.Error.Printf("Testing : %v", tt.name) + logger.Error.Printf("CurrentUser Testing : %v", tt.name) logger.Error.Print("==============================================================") t.Run(tt.name, func(t *testing.T) { @@ -303,11 +304,14 @@ func testCurrentUserHandler(t *testing.T, loginEmail string, loginCookie http.Co assert.Equal(t, tt.expectedStatus, w.Code) if tt.expectedStatus == http.StatusOK { - var response models.User + var response struct { + User models.User `json:"user"` + Subscriptions []models.SubscriptionModel `json:"subscriptions"` + } err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) - - assert.Equal(t, tt.expectedUserMail, response.Email) + // logger.Error.Printf("response: %#v", response) + assert.Equal(t, tt.expectedUserMail, response.User.Email) var newCookie *http.Cookie for _, cookie := range w.Result().Cookies() { if cookie.Name == "jwt" { @@ -346,6 +350,18 @@ func validateUser(assert bool, wantDBData map[string]interface{}) error { return fmt.Errorf("User entry query didn't met expectation: %v != %#v", assert, *users) } if assert { + user := (*users)[0] + // Check for mandate reference + if user.BankAccount.MandateReference == "" { + return fmt.Errorf("Mandate reference not generated for user: %s", user.Email) + } + + // Validate mandate reference format + expected := user.GenerateMandateReference() + if !strings.HasPrefix(user.BankAccount.MandateReference, expected) { + return fmt.Errorf("Mandate reference is invalid. Expected: %s, Got: %s", expected, user.BankAccount.MandateReference) + } + //check for email delivery messages := utils.SMTPGetMessages() for _, message := range messages { @@ -355,12 +371,12 @@ func validateUser(assert bool, wantDBData map[string]interface{}) error { return err } if strings.Contains(mail.Subject, constants.MailRegistrationSubject) { - if err := checkRegistrationMail(mail, &(*users)[0]); err != nil { + if err := checkRegistrationMail(mail, &user); err != nil { logger.Error.Printf("Error in checkRegistrationMail: %#v", err) return err } } else if strings.Contains(mail.Subject, constants.MailVerificationSubject) { - if err := checkVerificationMail(mail, &(*users)[0]); err != nil { + if err := checkVerificationMail(mail, &user); err != nil { logger.Error.Printf("Error in checkVerificationMail: %#v", err) return err } @@ -413,16 +429,6 @@ func testUpdateUser(t *testing.T, loginEmail string, loginCookie http.Cookie) { }, expectedStatus: http.StatusAccepted, }, - { - name: "Password Update", - setupCookie: func(req *http.Request) { - req.AddCookie(&loginCookie) - }, - updateFunc: func(u *models.User) { - u.Password = "NewPassword" - }, - expectedStatus: http.StatusAccepted, - }, { name: "Valid Update, invalid cookie", setupCookie: func(req *http.Request) { @@ -444,11 +450,80 @@ func testUpdateUser(t *testing.T, loginEmail string, loginCookie http.Cookie) { }, updateFunc: func(u *models.User) { u.Password = "" + u.FirstName = "John Updated" + u.LastName = "Doe Updated" + u.Phone = "01738484994" u.Email = "invalid-email" }, expectedStatus: http.StatusBadRequest, expectedError: "Invalid user data", }, + { + name: "Change LicenceNumber", + setupCookie: func(req *http.Request) { + req.AddCookie(&loginCookie) + }, + updateFunc: func(u *models.User) { + u.Password = "" + u.FirstName = "John Updated" + u.LastName = "Doe Updated" + u.Phone = "01738484994" + u.DriversLicence.LicenceNumber = "NEWNUMBER" + }, + expectedStatus: http.StatusAccepted, + }, + { + name: "Add category", + setupCookie: func(req *http.Request) { + req.AddCookie(&loginCookie) + }, + updateFunc: func(u *models.User) { + u.Password = "" + u.FirstName = "John Updated" + u.LastName = "Doe Updated" + u.Phone = "01738484994" + u.DriversLicence.LicenceNumber = "NEWNUMBER" + var licenceRepo repositories.DriversLicenceInterface = &repositories.DriversLicenceRepository{} + category, err := licenceRepo.FindCategoryByName("B") + assert.NoError(t, err) + u.DriversLicence.LicenceCategories = []models.LicenceCategory{category} + }, + expectedStatus: http.StatusAccepted, + }, + { + name: "Add 2 categories", + setupCookie: func(req *http.Request) { + req.AddCookie(&loginCookie) + }, + updateFunc: func(u *models.User) { + u.Password = "" + u.FirstName = "John Updated" + u.LastName = "Doe Updated" + u.Phone = "01738484994" + u.DriversLicence.LicenceNumber = "NEWNUMBER" + var licenceRepo repositories.DriversLicenceInterface = &repositories.DriversLicenceRepository{} + category, err := licenceRepo.FindCategoryByName("B") + category2, err := licenceRepo.FindCategoryByName("BE") + assert.NoError(t, err) + u.DriversLicence.LicenceCategories = []models.LicenceCategory{category, category2} + }, + expectedStatus: http.StatusAccepted, + }, + { + name: "Delete all categories", + setupCookie: func(req *http.Request) { + req.AddCookie(&loginCookie) + }, + updateFunc: func(u *models.User) { + u.Password = "" + u.FirstName = "John Updated" + u.LastName = "Doe Updated" + u.Phone = "01738484994" + u.DriversLicence.LicenceNumber = "NEWNUMBER" + u.DriversLicence.LicenceCategories = []models.LicenceCategory{} + }, + expectedStatus: http.StatusAccepted, + }, { name: "User ID mismatch while not admin", setupCookie: func(req *http.Request) { @@ -457,11 +532,28 @@ func testUpdateUser(t *testing.T, loginEmail string, loginCookie http.Cookie) { updateFunc: func(u *models.User) { u.Password = "" u.ID = 1 + u.LastName = "Doe Updated" + u.Phone = "01738484994" + u.DriversLicence.LicenceNumber = "NEWNUMBER" u.FirstName = "John Missing ID" }, expectedStatus: http.StatusForbidden, expectedError: "You are not authorized to update this user", }, + { + name: "Password Update", + setupCookie: func(req *http.Request) { + req.AddCookie(&loginCookie) + }, + updateFunc: func(u *models.User) { + u.Password = "" + u.LastName = "Doe Updated" + u.Phone = "01738484994" + u.DriversLicence.LicenceNumber = "NEWNUMBER" + u.Password = "NewPassword" + }, + expectedStatus: http.StatusAccepted, + }, // { // name: "Non-existent User", // setupCookie: func(req *http.Request) { @@ -476,7 +568,6 @@ func testUpdateUser(t *testing.T, loginEmail string, loginCookie http.Cookie) { // expectedError: "User not found", // }, } - for _, tt := range tests { logger.Error.Print("==============================================================") logger.Error.Printf("Update Testing : %v", tt.name) @@ -485,13 +576,13 @@ func testUpdateUser(t *testing.T, loginEmail string, loginCookie http.Cookie) { // Create a copy of the user and apply the updates updatedUser := user tt.updateFunc(&updatedUser) - // Convert user to JSON jsonData, err := json.Marshal(updatedUser) if err != nil { t.Fatalf("Failed to marshal user data: %v", err) } + logger.Error.Printf("Updated User: %#v", updatedUser) // Create request req, _ := http.NewRequest("PUT", "/users/"+strconv.FormatUint(uint64(user.ID), 10), bytes.NewBuffer(jsonData)) req.Header.Set("Content-Type", "application/json") @@ -523,20 +614,59 @@ func testUpdateUser(t *testing.T, loginEmail string, loginCookie http.Cookie) { // Verify the update in the database updatedUserFromDB, err := Uc.Service.GetUserByID(user.ID) - updatedUserFromDB.UpdatedAt = updatedUser.UpdatedAt - updatedUserFromDB.Membership.UpdatedAt = updatedUser.Membership.UpdatedAt - updatedUserFromDB.BankAccount.UpdatedAt = updatedUser.BankAccount.UpdatedAt - updatedUserFromDB.Verification.UpdatedAt = updatedUser.Verification.UpdatedAt - updatedUserFromDB.Membership.SubscriptionModel.UpdatedAt = updatedUser.Membership.SubscriptionModel.UpdatedAt + assert.NoError(t, err) + if updatedUser.Password == "" { assert.Equal(t, user.Password, (*updatedUserFromDB).Password) } else { assert.NotEqual(t, user.Password, (*updatedUserFromDB).Password) - updatedUser.Password = "" } + updatedUserFromDB.Password = "" - assert.NoError(t, err) - assert.Equal(t, updatedUser, *updatedUserFromDB, "Updated user in DB does not match expected user") + updatedUser.Password = "" + assert.Equal(t, updatedUser.FirstName, updatedUserFromDB.FirstName, "FirstName mismatch") + assert.Equal(t, updatedUser.LastName, updatedUserFromDB.LastName, "LastName mismatch") + assert.Equal(t, updatedUser.Email, updatedUserFromDB.Email, "Email mismatch") + assert.Equal(t, updatedUser.DateOfBirth, updatedUserFromDB.DateOfBirth, "DateOfBirth mismatch") + assert.Equal(t, updatedUser.Company, updatedUserFromDB.Company, "Company mismatch") + assert.Equal(t, updatedUser.Phone, updatedUserFromDB.Phone, "Phone mismatch") + assert.Equal(t, updatedUser.Notes, updatedUserFromDB.Notes, "Notes mismatch") + assert.Equal(t, updatedUser.ProfilePicture, updatedUserFromDB.ProfilePicture, "ProfilePicture mismatch") + assert.Equal(t, updatedUser.Address, updatedUserFromDB.Address, "Address mismatch") + assert.Equal(t, updatedUser.ZipCode, updatedUserFromDB.ZipCode, "ZipCode mismatch") + assert.Equal(t, updatedUser.City, updatedUserFromDB.City, "City mismatch") + assert.Equal(t, updatedUser.PaymentStatus, updatedUserFromDB.PaymentStatus, "PaymentStatus mismatch") + assert.Equal(t, updatedUser.Status, updatedUserFromDB.Status, "Status mismatch") + assert.Equal(t, updatedUser.RoleID, updatedUserFromDB.RoleID, "RoleID mismatch") + + // For nested structs, you might want to compare individual fields + assert.Equal(t, updatedUser.BankAccount.Bank, updatedUserFromDB.BankAccount.Bank, "BankAccount.Bank mismatch") + assert.Equal(t, updatedUser.BankAccount.AccountHolderName, updatedUserFromDB.BankAccount.AccountHolderName, "BankAccount.AccountHolderName mismatch") + assert.Equal(t, updatedUser.BankAccount.IBAN, updatedUserFromDB.BankAccount.IBAN, "BankAccount.IBAN mismatch") + assert.Equal(t, updatedUser.BankAccount.BIC, updatedUserFromDB.BankAccount.BIC, "BankAccount.BIC mismatch") + assert.Equal(t, updatedUser.BankAccount.MandateReference, updatedUserFromDB.BankAccount.MandateReference, "BankAccount.MandateReference mismatch") + + assert.Equal(t, updatedUser.Membership.StartDate, updatedUserFromDB.Membership.StartDate, "Membership.StartDate mismatch") + assert.Equal(t, updatedUser.Membership.EndDate, updatedUserFromDB.Membership.EndDate, "Membership.EndDate mismatch") + assert.Equal(t, updatedUser.Membership.Status, updatedUserFromDB.Membership.Status, "Membership.Status mismatch") + assert.Equal(t, updatedUser.Membership.SubscriptionModelID, updatedUserFromDB.Membership.SubscriptionModelID, "Membership.SubscriptionModelID mismatch") + assert.Equal(t, updatedUser.Membership.ParentMembershipID, updatedUserFromDB.Membership.ParentMembershipID, "Membership.ParentMembershipID mismatch") + + assert.Equal(t, updatedUser.DriversLicence.Status, updatedUserFromDB.DriversLicence.Status, "DriversLicence.Status mismatch") + assert.Equal(t, updatedUser.DriversLicence.LicenceNumber, updatedUserFromDB.DriversLicence.LicenceNumber, "DriversLicence.LicenceNumber mismatch") + assert.Equal(t, updatedUser.DriversLicence.IssuedDate, updatedUserFromDB.DriversLicence.IssuedDate, "DriversLicence.IssuedDate mismatch") + assert.Equal(t, updatedUser.DriversLicence.ExpirationDate, updatedUserFromDB.DriversLicence.ExpirationDate, "DriversLicence.ExpirationDate mismatch") + assert.Equal(t, updatedUser.DriversLicence.IssuingCountry, updatedUserFromDB.DriversLicence.IssuingCountry, "DriversLicence.IssuingCountry mismatch") + + // For slices or more complex nested structures, you might want to use deep equality checks + assert.ElementsMatch(t, updatedUser.Consents, updatedUserFromDB.Consents, "Consents mismatch") + if len(updatedUser.DriversLicence.LicenceCategories) > 0 { + for i := range updatedUser.DriversLicence.LicenceCategories { + assert.Equal(t, updatedUser.DriversLicence.LicenceCategories[i].Category, updatedUserFromDB.DriversLicence.LicenceCategories[i].Category, "LicenceCategory Category mismatch at index %d", i) + } + } else { + assert.Emptyf(t, updatedUserFromDB.DriversLicence.LicenceCategories, "Categories aren't empty when they should") + } } }) } @@ -822,7 +952,7 @@ func getTestUsers() []RegisterUserTest { { Name: "Correct Entry should pass", WantResponse: http.StatusCreated, - WantDBData: map[string]interface{}{"Email": "john.doe@example.com"}, + WantDBData: map[string]interface{}{"email": "john.doe@example.com"}, Assert: true, Input: GenerateInputJSON(customizeInput(func(user models.User) models.User { return user })), }, @@ -839,7 +969,7 @@ func getTestUsers() []RegisterUserTest { { Name: "Company present should pass", WantResponse: http.StatusCreated, - WantDBData: map[string]interface{}{"Email": "john.doe2@example.com"}, + WantDBData: map[string]interface{}{"email": "john.doe2@example.com"}, Assert: true, Input: GenerateInputJSON(customizeInput(func(user models.User) models.User { user.Email = "john.doe2@example.com" @@ -850,7 +980,7 @@ func getTestUsers() []RegisterUserTest { { Name: "Subscription constraints not entered; should fail", WantResponse: http.StatusNotAcceptable, - WantDBData: map[string]interface{}{"Email": "john.junior.doe@example.com"}, + WantDBData: map[string]interface{}{"email": "john.junior.doe@example.com"}, Assert: false, Input: GenerateInputJSON(customizeInput(func(user models.User) models.User { user.Email = "john.junior.doe@example.com" @@ -861,7 +991,7 @@ func getTestUsers() []RegisterUserTest { { Name: "Subscription constraints wrong; should fail", WantResponse: http.StatusNotAcceptable, - WantDBData: map[string]interface{}{"Email": "john.junior.doe@example.com"}, + WantDBData: map[string]interface{}{"email": "john.junior.doe@example.com"}, Assert: false, Input: GenerateInputJSON(customizeInput(func(user models.User) models.User { user.Email = "john.junior.doe@example.com" @@ -873,7 +1003,7 @@ func getTestUsers() []RegisterUserTest { { Name: "Subscription constraints correct, should pass", WantResponse: http.StatusCreated, - WantDBData: map[string]interface{}{"Email": "john.junior.doe@example.com"}, + WantDBData: map[string]interface{}{"email": "john.junior.doe@example.com"}, Assert: true, Input: GenerateInputJSON(customizeInput(func(user models.User) models.User { user.Email = "john.junior.doe@example.com" @@ -882,5 +1012,16 @@ func getTestUsers() []RegisterUserTest { return user })), }, + { + Name: "Correct Entry with Mandate Reference", + WantResponse: http.StatusCreated, + WantDBData: map[string]interface{}{"email": "john.mandate@example.com"}, + Assert: true, + Input: GenerateInputJSON(customizeInput(func(user models.User) models.User { + user.Email = "john.mandate@example.com" + user.BankAccount.IBAN = "DE89370400440532013000" + return user + })), + }, } }